Tôi nên phân tích cú pháp JSON bằng Node.js như thế nào? Có một số mô-đun sẽ xác nhận và phân tích JSON một cách an toàn không?
Tôi nên phân tích cú pháp JSON bằng Node.js như thế nào? Có một số mô-đun sẽ xác nhận và phân tích JSON một cách an toàn không?
Câu trả lời:
Bạn chỉ có thể sử dụng JSON.parse
.
Định nghĩa của JSON
đối tượng là một phần của đặc tả ECMAScript 5 . node.js được xây dựng trên công cụ V8 của Google Chrome , tuân thủ tiêu chuẩn ECMA. Do đó, node.js cũng có một đối tượng toàn cầu [docs] .JSON
Lưu ý - JSON.parse
có thể buộc luồng hiện tại vì đây là phương thức đồng bộ. Vì vậy, nếu bạn dự định phân tích các đối tượng JSON lớn, hãy sử dụng trình phân tích cú pháp json trực tuyến.
bạn có thể yêu cầu các tập tin .json.
var parsedJSON = require('./file-name');
Ví dụ: nếu bạn có một config.json
tệp trong cùng thư mục với tệp mã nguồn bạn sẽ sử dụng:
var config = require('./config.json');
hoặc (phần mở rộng tập tin có thể được bỏ qua):
var config = require('./config');
lưu ý rằng đó require
là đồng bộ và chỉ đọc tệp một lần , các cuộc gọi sau trả về kết quả từ bộ đệm
Cũng lưu ý Bạn chỉ nên sử dụng điều này cho các tệp cục bộ dưới sự kiểm soát tuyệt đối của mình, vì nó có khả năng thực thi bất kỳ mã nào trong tệp.
require
là đồng bộ. fs.readFile
Thay vào đó, nếu bạn muốn đồng bộ hóa, hãy sử dụngJSON.parse
.json
tiện ích mở rộng! Nếu tệp của bạn KHÔNG có .json
phần mở rộng, yêu cầu sẽ không coi nó là tệp json.
Bạn có thể sử dụngJSON.parse()
.
Bạn sẽ có thể sử dụng JSON
đối tượng trên bất kỳ triển khai JavaScript tương thích ECMAScript 5 nào . Và V8 , trên đó Node.js được xây dựng là một trong số đó.
Lưu ý: Nếu bạn đang sử dụng tệp JSON để lưu trữ thông tin nhạy cảm (ví dụ: mật khẩu), đó là cách làm sai. Xem cách Heroku làm điều đó: https://devcenter.heroku.com/articles/config-vars#setting-up-config-vars-for-a-deployed-application . Tìm hiểu cách nền tảng của bạn làm điều đó và sử dụng
process.env
để truy xuất các vars cấu hình từ bên trong mã.
var str = '{ "name": "John Doe", "age": 42 }';
var obj = JSON.parse(str);
Bạn sẽ phải thực hiện một số thao tác tập tin với fs
mô-đun.
var fs = require('fs');
fs.readFile('/path/to/file.json', 'utf8', function (err, data) {
if (err) throw err; // we'll not consider error handling for now
var obj = JSON.parse(data);
});
var fs = require('fs');
var json = JSON.parse(fs.readFileSync('/path/to/file.json', 'utf8'));
require
? Nghĩ lại!Đôi khi bạn có thể sử dụngrequire
:
var obj = require('path/to/file.json');
Nhưng, tôi không khuyến nghị điều này vì nhiều lý do:
require
là đồng bộ. Nếu bạn có một tệp JSON rất lớn, nó sẽ bóp nghẹt vòng lặp sự kiện của bạn. Bạn thực sự cần phải sử dụng JSON.parse
với fs.readFile
.require
sẽ chỉ đọc tệp một lần . Các cuộc gọi tiếp theo require
cho cùng một tệp sẽ trả về một bản sao được lưu trong bộ nhớ cache. Không phải là một ý tưởng tốt nếu bạn muốn đọc một .json
tập tin được cập nhật liên tục. Bạn có thể sử dụng một hack . Nhưng tại thời điểm này, nó dễ sử dụng hơn fs
..json
phần mở rộng, require
sẽ không coi nội dung của tệp là JSON.Nghiêm túc! Sử dụngJSON.parse
.
load-json-file
mô-đunNếu bạn đang đọc số lượng lớn .json
tệp, (và nếu bạn cực kỳ lười biếng), sẽ rất khó chịu khi viết mã soạn sẵn mỗi lần. Bạn có thể lưu một số ký tự bằng cách sử dụng load-json-file
mô-đun.
const loadJsonFile = require('load-json-file');
loadJsonFile('/path/to/file.json').then(json => {
// `json` contains the parsed object
});
let obj = loadJsonFile.sync('/path/to/file.json');
Nếu nội dung JSON được truyền phát qua mạng, bạn cần sử dụng trình phân tích cú pháp JSON truyền phát. Nếu không, nó sẽ kết nối bộ xử lý của bạn và bóp nghẹt vòng lặp sự kiện của bạn cho đến khi nội dung JSON được truyền phát đầy đủ.
Có rất nhiều gói có sẵn trong NPM cho việc này. Chọn những gì tốt nhất cho bạn.
Nếu bạn không chắc chắn bất cứ điều gì được chuyển đến JSON.parse()
là JSON hợp lệ , hãy đảm bảo gửi cuộc gọi đến JSON.parse()
bên trong một try/catch
khối. Một người dùng được cung cấp chuỗi JSON có thể làm hỏng ứng dụng của bạn và thậm chí có thể dẫn đến các lỗ hổng bảo mật. Đảm bảo xử lý lỗi được thực hiện nếu bạn phân tích cú pháp JSON được cung cấp bên ngoài.
and could even lead to security holes
Vì tò mò, làm thế nào?
<script>...
và lỗi được đổ sang phía máy khách, bạn có lỗi XSS ngay tại đó. Do đó, IMO rất quan trọng để xử lý các lỗi JSON ngay tại nơi bạn phân tích cú pháp.
require
để bao gồm JSON?" và thậm chí không bận tâm đến việc ghi lại các tác dụng phụ. Điều này cũng có nghĩa là yêu cầu chấp nhận các tệp bằng hai ngôn ngữ: JavaScript và JSON (không có chúng không giống nhau). Quá nhiều cho SRP.
sử dụng đối tượng JSON :
JSON.parse(str);
Một ví dụ khác về JSON.parse:
var fs = require('fs');
var file = __dirname + '/config.json';
fs.readFile(file, 'utf8', function (err, data) {
if (err) {
console.log('Error: ' + err);
return;
}
data = JSON.parse(data);
console.dir(data);
});
Tôi muốn đề cập rằng có những lựa chọn thay thế cho đối tượng JSON toàn cầu.
JSON.parse
và JSON.stringify
đều đồng bộ, vì vậy nếu bạn muốn xử lý các đối tượng lớn, bạn có thể muốn kiểm tra một số mô-đun JSON không đồng bộ.
Hãy xem: https://github.com/joyent/node/wiki/Modules#wiki-parsers-json
JSON.parse
toàn bộ ứng dụng của bạn sẽ gặp sự cố hoặc, bằng cách sử dụng process.on('uncaughtException', function(err) { ... });
, cuối cùng sẽ không có cơ hội gửi lỗi "JSON không đúng định dạng" cho người dùng.
async
trình phân tích cú pháp? Tôi đã không tìm thấy nó.
Bao gồm node-fs
thư viện.
var fs = require("fs");
var file = JSON.parse(fs.readFileSync("./PATH/data.json", "utf8"));
Để biết thêm thông tin về thư viện 'fs', hãy tham khảo tài liệu tại http://nodejs.org/api/fs.html
Vì bạn không biết rằng chuỗi của bạn thực sự hợp lệ, tôi sẽ đặt chuỗi đầu tiên vào một thử bắt. Ngoài ra, vì các khối bắt thử không được tối ưu hóa bởi nút, tôi sẽ đặt toàn bộ vào một chức năng khác:
function tryParseJson(str) {
try {
return JSON.parse(str);
} catch (ex) {
return null;
}
}
HOẶC theo "kiểu không đồng bộ"
function tryParseJson(str, callback) {
process.nextTick(function () {
try {
callback(null, JSON.parse(str));
} catch (ex) {
callback(ex)
}
})
}
Phân tích luồng JSON? Sử dụng JSONStream
.
var request = require('request')
, JSONStream = require('JSONStream')
request({url: 'http://isaacs.couchone.com/registry/_all_docs'})
.pipe(JSONStream.parse('rows.*'))
.pipe(es.mapSync(function (data) {
return data
}))
Mọi người ở đây đã nói về JSON.parse, vì vậy tôi nghĩ đến việc nói điều gì đó khác. Có một mô-đun tuyệt vời Kết nối với nhiều phần mềm trung gian để giúp phát triển ứng dụng dễ dàng và tốt hơn. Một trong những phần mềm trung gian là bodyParser . Nó phân tích JSON, html-hình thức và vv Ngoài ra còn có một trung gian cụ thể cho JSON phân tích chỉ noop .
Hãy xem các liên kết ở trên, nó có thể thực sự hữu ích cho bạn.
JSON.parse("your string");
Đó là tất cả.
như các câu trả lời khác ở đây đã đề cập, có lẽ bạn muốn yêu cầu tệp json cục bộ mà bạn biết là an toàn và hiện tại, giống như tệp cấu hình:
var objectFromRequire = require('path/to/my/config.json');
hoặc để sử dụng đối tượng JSON toàn cầu để phân tích giá trị chuỗi thành một đối tượng:
var stringContainingJson = '\"json that is obtained from somewhere\"';
var objectFromParse = JSON.parse(stringContainingJson);
lưu ý rằng khi bạn yêu cầu một tệp, nội dung của tệp đó được đánh giá, điều này gây ra rủi ro bảo mật trong trường hợp đó không phải là tệp json mà là tệp js.
Ở đây, tôi đã xuất bản một bản demo nơi bạn có thể thấy cả hai phương thức và chơi với chúng trực tuyến (ví dụ phân tích cú pháp là trong tệp app.js - sau đó nhấp vào nút chạy và xem kết quả trong thiết bị đầu cuối): http: // staging1 .codefresh.io / labs / api / env / json-parse-example
bạn có thể sửa đổi mã và xem tác động ...
Sử dụng JSON cho cấu hình của bạn với Node.js? Đọc này và nhận được các kỹ năng cấu hình của bạn hơn 9000 ...
Lưu ý: Mọi người cho rằng data = quiries ('./ data.json'); là một rủi ro bảo mật và hạ thấp câu trả lời của mọi người với lòng nhiệt thành: Bạn hoàn toàn sai lầm . Hãy thử đặt phi JSON trong tập tin đó ... Node sẽ cung cấp cho bạn một lỗi, chính xác như nó sẽ nếu bạn đã làm điều tương tự với nhiều chậm hơn và khó khăn hơn để mã của nhãn hiệu tập đọc và sau đó tiếp theo JSON.parse (). Hãy ngừng truyền bá thông tin sai lệch; bạn đang làm tổn thương thế giới, không giúp đỡ. Nút được thiết kế để cho phép điều này; nó không phải là một rủi ro bảo mật!
Các ứng dụng phù hợp có hơn 3 lớp cấu hình:
Hầu hết các nhà phát triển đối xử với cấu hình máy chủ và ứng dụng của họ như thể nó có thể thay đổi. Nó không thể. Bạn có thể thay đổi các lớp từ các lớp cao hơn chồng lên nhau, nhưng bạn đang sửa đổi các yêu cầu cơ bản . Một số điều cần tồn tại! Làm cho cấu hình của bạn hoạt động giống như nó bất biến, bởi vì một số trong đó về cơ bản là, giống như mã nguồn của bạn.
Không thấy rằng nhiều nội dung của bạn sẽ không thay đổi sau khi khởi động dẫn đến các kiểu chống lại như xả rác cấu hình của bạn với các khối thử / bắt và giả vờ bạn có thể tiếp tục mà không cần ứng dụng thiết lập đúng. Bạn không thể. Nếu bạn có thể, thuộc lớp cấu hình cộng đồng / người dùng, không phải lớp cấu hình máy chủ / ứng dụng. Bạn đang làm sai. Các công cụ tùy chọn nên được xếp chồng lên trên khi ứng dụng hoàn thành bootstrap.
Dừng đập đầu vào tường: Cấu hình của bạn phải cực kỳ đơn giản .
Hãy xem việc dễ dàng thiết lập một cái gì đó phức tạp như một khung dịch vụ không xác định giao thức và dữ liệu không sử dụng dữ liệu bằng cách sử dụng tệp cấu hình json đơn giản và tệp app.js đơn giản ...
container-config.js ...
{
"service": {
"type" : "http",
"name" : "login",
"port" : 8085
},
"data": {
"type" : "mysql",
"host" : "localhost",
"user" : "notRoot",
"pass" : "oober1337",
"name" : "connect"
}
}
index.js ... (công cụ cung cấp năng lượng cho mọi thứ)
var config = require('./container-config.json'); // Get our service configuration.
var data = require(config.data.type); // Load our data source plugin ('npm install mysql' for mysql).
var service = require(config.service.type); // Load our service plugin ('http' is built-in to node).
var processor = require('./app.js'); // Load our processor (the code you write).
var connection = data.createConnection({ host: config.data.host, user: config.data.user, password: config.data.pass, database: config.data.name });
var server = service.createServer(processor);
connection.connect();
server.listen(config.service.port, function() { console.log("%s service listening on port %s", config.service.type, config.service.port); });
app.js ... (mã cung cấp dịch vụ bất khả tri về giao thức và nguồn dữ liệu của bạn)
module.exports = function(request, response){
response.end('Responding to: ' + request.url);
}
Sử dụng mẫu này, giờ đây bạn có thể tải công cụ cấu hình cộng đồng và người dùng lên trên ứng dụng đã khởi động của mình, dev ops đã sẵn sàng chuyển công việc của bạn vào một thùng chứa và mở rộng quy mô. Bạn đang đọc cho nhiều người. Vùng đất người dùng bị cô lập. Bây giờ bạn có thể phân tách mối quan tâm về giao thức dịch vụ nào bạn đang sử dụng, loại cơ sở dữ liệu nào bạn đang sử dụng và chỉ tập trung vào viết mã tốt.
Bởi vì bạn đang sử dụng các lớp, bạn có thể dựa vào một nguồn sự thật duy nhất cho mọi thứ, bất cứ lúc nào (đối tượng cấu hình lớp) và tránh kiểm tra lỗi ở mỗi bước, lo lắng về "oh crap, tôi sẽ làm thế nào làm việc mà không có cấu hình phù hợp?!? ".
Giải pháp của tôi:
var fs = require('fs');
var file = __dirname + '/config.json';
fs.readFile(file, 'utf8', function (err, data) {
if (err) {
console.log('Error: ' + err);
return;
}
data = JSON.parse(data);
console.dir(data);
});
TypeError: path must be a string or Buffer
lỗi - có ý tưởng nào để bắt đầu gỡ lỗi vấn đề này không?
Chỉ muốn hoàn thành câu trả lời (khi tôi vật lộn với nó một lúc), muốn chỉ ra cách truy cập thông tin json, ví dụ này cho thấy việc truy cập Json Array:
var request = require('request');
request('https://server/run?oper=get_groups_joined_by_user_id&user_id=5111298845048832', function (error, response, body) {
if (!error && response.statusCode == 200) {
var jsonArr = JSON.parse(body);
console.log(jsonArr);
console.log("group id:" + jsonArr[0].id);
}
})
Chỉ cần làm cho điều này trở nên phức tạp nhất có thể, và mang lại càng nhiều gói càng tốt ...
const fs = require('fs');
const bluebird = require('bluebird');
const _ = require('lodash');
const readTextFile = _.partial(bluebird.promisify(fs.readFile), _, {encoding:'utf8',flag:'r'});
const readJsonFile = filename => readTextFile(filename).then(JSON.parse);
Điều này cho phép bạn làm:
var dataPromise = readJsonFile("foo.json");
dataPromise.then(console.log);
Hoặc nếu bạn đang sử dụng async / await:
let data = await readJsonFile("foo.json");
Ưu điểm so với việc chỉ sử dụng readFileSync
là máy chủ Node của bạn có thể xử lý các yêu cầu khác trong khi tệp đang được đọc trên đĩa.
JSON.parse sẽ không đảm bảo an toàn cho chuỗi json mà bạn đang phân tích cú pháp. Bạn nên xem một thư viện như json-safe-parse hoặc một thư viện tương tự.
Từ trang npm json-safe-parse:
JSON.parse là tuyệt vời, nhưng nó có một lỗ hổng nghiêm trọng trong ngữ cảnh của JavaScript: nó cho phép bạn ghi đè các thuộc tính được kế thừa. Điều này có thể trở thành vấn đề nếu bạn phân tích cú pháp JSON từ một nguồn không đáng tin cậy (ví dụ: người dùng) và gọi các hàm trên đó mà bạn mong đợi tồn tại.
Tận dụng chức năng cố gắng của Lodash để trả về một đối tượng lỗi mà bạn có thể xử lý bằng hàm isError.
// Returns an error object on failure
function parseJSON(jsonString) {
return _.attempt(JSON.parse.bind(null, jsonString));
}
// Example Usage
var goodJson = '{"id":123}';
var badJson = '{id:123}';
var goodResult = parseJSON(goodJson);
var badResult = parseJSON(badJson);
if (_.isError(goodResult)) {
console.log('goodResult: handle error');
} else {
console.log('goodResult: continue processing');
}
// > goodResult: continue processing
if (_.isError(badResult)) {
console.log('badResult: handle error');
} else {
console.log('badResult: continue processing');
}
// > badResult: handle error
.bind
thay vì chỉ sử dụng _.atteem (JSON.parse, str)
Luôn chắc chắn sử dụng JSON.parse trong khối thử bắt vì nút luôn đưa ra Lỗi không mong muốn nếu bạn có một số dữ liệu bị hỏng trong json, vì vậy hãy sử dụng mã này thay vì JSON.Pude đơn giản
try{
JSON.parse(data)
}
catch(e){
throw new Error("data is corrupted")
}
Nếu bạn muốn thêm một số nhận xét trong JSON của mình và cho phép dấu phẩy bạn có thể muốn sử dụng bên dưới triển khai:
var fs = require('fs');
var data = parseJsData('./message.json');
console.log('[INFO] data:', data);
function parseJsData(filename) {
var json = fs.readFileSync(filename, 'utf8')
.replace(/\s*\/\/.+/g, '')
.replace(/,(\s*\})/g, '}')
;
return JSON.parse(json);
}
Lưu ý rằng nó có thể không hoạt động tốt nếu bạn có một cái gì đó giống như "abc": "foo // bar"
trong JSON của bạn. Vậy YMMV.
Nếu tệp nguồn JSON khá lớn, có thể muốn xem xét tuyến không đồng bộ thông qua cách tiếp cận async / await riêng với Node.js 8.0 như sau
const fs = require('fs')
const fsReadFile = (fileName) => {
fileName = `${__dirname}/${fileName}`
return new Promise((resolve, reject) => {
fs.readFile(fileName, 'utf8', (error, data) => {
if (!error && data) {
resolve(data)
} else {
reject(error);
}
});
})
}
async function parseJSON(fileName) {
try {
return JSON.parse(await fsReadFile(fileName));
} catch (err) {
return { Error: `Something has gone wrong: ${err}` };
}
}
parseJSON('veryBigFile.json')
.then(res => console.log(res))
.catch(err => console.log(err))
Tôi sử dụng fs-thêm . Tôi thích nó rất nhiều vì mặc dù nó hỗ trợ các cuộc gọi lại - nó cũng hỗ trợ Promise . Vì vậy, nó chỉ cho phép tôi viết mã theo cách dễ đọc hơn nhiều:
const fs = require('fs-extra');
fs.readJson("path/to/foo.json").then(obj => {
//Do dome stuff with obj
})
.catch(err => {
console.error(err);
});
Nó cũng có nhiều phương thức hữu ích không đi kèm với fs
mô-đun tiêu chuẩn và trên hết, nó cũng kết nối các phương thức từ fs
mô-đun gốc và quảng bá chúng.
LƯU Ý: Bạn vẫn có thể sử dụng các phương thức Node.js riêng. Chúng được quảng cáo và sao chép qua fs-Extra. Xem ghi chú trên
fs.read()
&fs.write()
Vì vậy, về cơ bản tất cả các lợi thế. Tôi hy vọng những người khác tìm thấy điều này hữu ích.
Nếu bạn cần phân tích JSON bằng Node.js một cách an toàn (hay còn gọi là: người dùng có thể nhập dữ liệu hoặc API công khai), tôi sẽ khuyên bạn nên sử dụng safe-json-parse .
Việc sử dụng giống như mặc định JSON.parse
nhưng nó sẽ bảo vệ mã của bạn khỏi:
const badJson = '{ "a": 5, "b": 6, "__proto__": { "x": 7 }, "constructor": {"prototype": {"bar": "baz"} } }'
const infected = JSON.parse(badJson)
console.log(infected.x) // print undefined
const x = Object.assign({}, infected)
console.log(x.x) // print 7
const sjson = require('secure-json-parse')
console.log(sjson.parse(badJson)) // it will throw by default, you can ignore malicious data also
Bạn có thể sử dụng JSON.parse () (là một hàm tích hợp có thể sẽ buộc bạn phải bọc nó bằng các câu lệnh try-Catch).
Hoặc sử dụng một số thư viện npm phân tích cú pháp JSON, một cái gì đó như json-parse-hoặc
Sử dụng cái này để ở bên an toàn
var data = JSON.parse(Buffer.concat(arr).toString());
NodeJs là một máy chủ dựa trên JavaScript , vì vậy bạn có thể thực hiện theo cách bạn làm điều đó trong JavaScript thuần túy ...
Hãy tưởng tượng bạn có điều này Json trong NodeJs ...
var details = '{ "name": "Alireza Dezfoolian", "netWorth": "$0" }';
var obj = JSON.parse(details);
Và bạn có thể làm ở trên để có được một phiên bản phân tích cú pháp của bạn ...
Như đã đề cập trong các câu trả lời ở trên, chúng tôi có thể sử dụng JSON.parse()
để phân tích các chuỗi thành JSON Nhưng trước khi phân tích cú pháp, hãy chắc chắn phân tích dữ liệu chính xác nếu không nó có thể làm giảm toàn bộ ứng dụng của bạn
sử dụng nó như thế này là an toàn
let parsedObj = {}
try {
parsedObj = JSON.parse(data);
} catch(e) {
console.log("Cannot parse because data is not is proper json format")
}
Sử dụng JSON.parse(str);
. Đọc thêm về nó ở đây .
Dưới đây là một số ví dụ:
var jsonStr = '{"result":true, "count":42}';
obj = JSON.parse(jsonStr);
console.log(obj.count); // expected output: 42
console.log(obj.result); // expected output: true
Thật đơn giản, bạn có thể chuyển đổi JSON thành chuỗi bằng cách sử dụng JSON.stringify(json_obj)
và chuyển đổi chuỗi thành JSON bằng cách sử dụng JSON.parse("your json string")
.