Come devo analizzare JSON usando Node.js? Esiste un modulo che convaliderà e analizzerà JSON in modo sicuro?
Come devo analizzare JSON usando Node.js? Esiste un modulo che convaliderà e analizzerà JSON in modo sicuro?
Risposte:
Puoi semplicemente usare JSON.parse
.
La definizione JSON
dell'oggetto fa parte della specifica ECMAScript 5 . node.js è basato sul motore V8 di Google Chrome , che aderisce allo standard ECMA. Pertanto, node.js ha anche un oggetto globale [docs]JSON
.
Nota: JSON.parse
può legare il thread corrente perché è un metodo sincrono. Quindi, se stai pianificando di analizzare grandi oggetti JSON usa un parser json in streaming.
puoi richiedere file .json.
var parsedJSON = require('./file-name');
Ad esempio se hai un config.json
file nella stessa directory del tuo file di codice sorgente dovresti usare:
var config = require('./config.json');
oppure (l'estensione del file può essere omessa):
var config = require('./config');
si noti che require
è sincrono e legge il file solo una volta , le chiamate seguenti restituiscono il risultato dalla cache
Nota anche che dovresti usarlo solo per i file locali sotto il tuo controllo assoluto, poiché potenzialmente esegue qualsiasi codice all'interno del file.
require
è sincrono. Se si desidera utilizzare ASYNC amichevole fs.readFile
invece conJSON.parse
.json
estensione! Se il tuo file NON ha l' .json
estensione, request non lo tratterà come un file json.
È possibile utilizzareJSON.parse()
.
Dovresti essere in grado di utilizzare l' JSON
oggetto su qualsiasi implementazione JavaScript compatibile ECMAScript 5 . E V8 , su cui è costruito Node.js è uno di questi.
Nota: se si utilizza un file JSON per archiviare informazioni riservate (ad esempio password), questo è il modo sbagliato di farlo. Guarda come lo fa Heroku: https://devcenter.heroku.com/articles/config-vars#setting-up-config-vars-for-a-deployed-application . Scopri come la tua piattaforma lo fa e usa
process.env
per recuperare le configurazioni dal codice.
var str = '{ "name": "John Doe", "age": 42 }';
var obj = JSON.parse(str);
Dovrai fare alcune operazioni sui file con il fs
modulo.
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
? Pensa di nuovo!var obj = require('path/to/file.json');
Ma non lo consiglio per diversi motivi:
require
è sincrono. Se si dispone di un file JSON molto grande, si bloccherà il ciclo degli eventi. Hai davvero bisogno di usare JSON.parse
con fs.readFile
.require
leggerà il file solo una volta . Le chiamate successive a require
per lo stesso file restituiranno una copia memorizzata nella cache. Non è una buona idea se vuoi leggere un .json
file che viene continuamente aggiornato. Potresti usare un hack . Ma a questo punto, è più semplice da usare fs
..json
un'estensione, require
non tratterà il contenuto del file come JSON.Sul serio! UsaJSON.parse
.
load-json-file
moduloSe stai leggendo un gran numero di .json
file (e se sei estremamente pigro), diventa fastidioso scrivere ogni volta il codice del boilerplate. Puoi salvare alcuni personaggi usando il load-json-file
modulo.
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');
Se il contenuto JSON viene trasmesso in streaming sulla rete, è necessario utilizzare un parser JSON in streaming. Altrimenti legherà il tuo processore e bloccherà il tuo loop degli eventi fino a quando il contenuto JSON non sarà completamente trasmesso in streaming.
Per questo ci sono molti pacchetti disponibili in NPM . Scegli ciò che è meglio per te.
Se non si è sicuri che tutto ciò che viene passato JSON.parse()
sia JSON valido , assicurarsi di racchiudere la chiamata JSON.parse()
all'interno di un try/catch
blocco. Una stringa JSON fornita da un utente potrebbe arrestare in modo anomalo l'applicazione e persino portare a falle nella sicurezza. Assicurarsi che venga eseguita la gestione degli errori se si analizza JSON fornito esternamente.
and could even lead to security holes
per curiosità, come?
<script>...
e l'errore si riversava sul lato client, c'è un bug XSS proprio lì. Pertanto, IMO è importante gestire gli errori JSON proprio dove lo analizzi.
require
includere JSON?" e non si è nemmeno preoccupato di documentare gli effetti collaterali. Ciò significava anche che richiedono accettare file in due lingue: JavaScript e JSON (no, non sono gli stessi). Questo per quanto riguarda SRP.
usa l' oggetto JSON :
JSON.parse(str);
Un altro esempio di 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);
});
Vorrei menzionare che esistono alternative all'oggetto JSON globale.
JSON.parse
e JSON.stringify
sono entrambi sincroni, quindi se si desidera gestire oggetti di grandi dimensioni, è possibile verificare alcuni dei moduli JSON asincroni.
Dai un'occhiata: https://github.com/joyent/node/wiki/Modules#wiki-parsers-json
JSON.parse
dall'intera applicazione si arresta in modo anomalo o, utilizzando process.on('uncaughtException', function(err) { ... });
, alla fine non ci sarà alcuna possibilità di inviare all'utente un errore "JSON non valido".
async
parser? Non l'ho trovato.
Includi la node-fs
biblioteca.
var fs = require("fs");
var file = JSON.parse(fs.readFileSync("./PATH/data.json", "utf8"));
Per ulteriori informazioni sulla libreria "fs", consultare la documentazione su http://nodejs.org/api/fs.html
Dal momento che non sai che la tua stringa è effettivamente valida, la metterei prima in un tentativo di cattura. Inoltre, poiché i blocchi di prova non sono ottimizzati per nodo, inserirò l'intera cosa in un'altra funzione:
function tryParseJson(str) {
try {
return JSON.parse(str);
} catch (ex) {
return null;
}
}
O in "stile asincrono"
function tryParseJson(str, callback) {
process.nextTick(function () {
try {
callback(null, JSON.parse(str));
} catch (ex) {
callback(ex)
}
})
}
Stai analizzando un flusso JSON? Usa 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
}))
Tutti qui hanno parlato di JSON.parse, quindi ho pensato di dire qualcos'altro. Esiste un ottimo modulo Connetti con molti middleware per rendere lo sviluppo di app più semplice e migliore. Uno dei middleware è bodyParser . Analizza JSON, html-form ed ecc. Esiste anche un middleware specifico per JSON che analizza solo noop .
Dai un'occhiata ai link sopra, potrebbe essere davvero utile per te.
JSON.parse("your string");
È tutto.
come altre risposte qui menzionate, probabilmente vorrai richiedere un file json locale che sai che è sicuro e presente, come un file di configurazione:
var objectFromRequire = require('path/to/my/config.json');
o per utilizzare l'oggetto JSON globale per analizzare un valore di stringa in un oggetto:
var stringContainingJson = '\"json that is obtained from somewhere\"';
var objectFromParse = JSON.parse(stringContainingJson);
notare che quando si richiede un file viene valutato il contenuto di quel file, il che introduce un rischio per la sicurezza nel caso in cui non sia un file json ma un file js.
qui, ho pubblicato una demo in cui è possibile visualizzare entrambi i metodi e giocare online (l'esempio di analisi è nel file app.js, quindi fare clic sul pulsante Esegui e vedere il risultato nel terminale): http: // staging1 .codefresh.io / laboratori / api / ENV / jSON-parse-example
puoi modificare il codice e vedere l'impatto ...
Usi JSON per la tua configurazione con Node.js? Leggi questo e ottieni le tue abilità di configurazione oltre 9000 ...
Nota: persone che affermano che data = request ('./ data.json'); è un rischio per la sicurezza e sottovalutare le risposte delle persone con zelo zelante: sbagli esattamente e completamente . Prova a posizionare non JSON in quel file ... Il nodo ti darà un errore, esattamente come farebbe se avessi fatto la stessa cosa con la lettura manuale dei file molto più lenta e più difficile da codificare e successivamente con JSON.parse (). Si prega di smettere di diffondere disinformazione; stai facendo del male al mondo, non stai aiutando. Il nodo è stato progettato per consentire ciò; non è un rischio per la sicurezza!
Le applicazioni appropriate sono disponibili in 3+ livelli di configurazione:
La maggior parte degli sviluppatori considera la configurazione del proprio server e app come se potesse cambiare. Non può. Puoi sovrapporre le modifiche da livelli superiori uno sopra l'altro, ma stai modificando i requisiti di base . Alcune cose devono esistere! Rendi la tua configurazione come se fosse immutabile, perché in parte lo è, proprio come il tuo codice sorgente.
Non riuscire a vedere che molte delle tue cose non cambieranno dopo l'avvio porta a anti-schemi come sporcare il caricamento della configurazione con blocchi try / catch e far finta di poter continuare senza la corretta applicazione di installazione. Non puoi. Se possibile, appartiene al livello di configurazione comunità / utente, non al livello di configurazione server / app. Lo stai solo facendo male. Le cose opzionali dovrebbero essere sovrapposte quando l'applicazione termina il bootstrap.
Smetti di sbattere la testa contro il muro: la tua configurazione dovrebbe essere ultra semplice .
Dai un'occhiata a quanto è facile configurare qualcosa di così complesso come un framework di servizi indipendente dal protocollo e indipendente dall'origine dati usando un semplice file json config e un semplice file app.js ...
container-config.js ...
{
"service": {
"type" : "http",
"name" : "login",
"port" : 8085
},
"data": {
"type" : "mysql",
"host" : "localhost",
"user" : "notRoot",
"pass" : "oober1337",
"name" : "connect"
}
}
index.js ... (il motore che alimenta tutto)
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 ... (il codice che alimenta il tuo servizio agnostico basato sul protocollo e sull'origine dati)
module.exports = function(request, response){
response.end('Responding to: ' + request.url);
}
Usando questo modello, ora puoi caricare elementi di configurazione della comunità e dell'utente sulla tua app avviata, gli sviluppatori sono pronti a trasferire il tuo lavoro in un contenitore e ridimensionarlo. Sei letto per multi-tenant. Userland è isolato. Ora puoi separare le preoccupazioni su quale protocollo di servizio stai usando, quale tipo di database stai usando e concentrarti solo sulla scrittura di un buon codice.
Perché si sta utilizzando i livelli, si può fare affidamento su una sola fonte di verità per tutto, in qualsiasi momento (l'oggetto di configurazione a strati), e controlli di errore da evitare a ogni passo, preoccuparsi di "Oh merda, come faccio a fare questo lavorare senza un'adeguata configurazione?!? ".
La mia soluzione:
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
errori - hai idea di dove iniziare a eseguire il debug di questo problema?
Voglio solo completare la risposta (mentre ho lottato con essa per un po '), voglio mostrare come accedere alle informazioni json, questo esempio mostra l'accesso a 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);
}
})
Solo per renderlo il più complicato possibile e portare il maggior numero possibile di pacchetti ...
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);
Questo ti permette di fare:
var dataPromise = readJsonFile("foo.json");
dataPromise.then(console.log);
O se stai usando asincrono / wait:
let data = await readJsonFile("foo.json");
Il vantaggio rispetto al solo utilizzo readFileSync
è che il tuo server Node può elaborare altre richieste mentre il file viene letto dal disco.
JSON.parse non garantirà la sicurezza della stringa json che stai analizzando. Dovresti guardare una libreria come json-safe-parse o una libreria simile.
Dalla pagina npm json-safe-parse:
JSON.parse è eccezionale, ma ha un grave difetto nel contesto di JavaScript: ti consente di sovrascrivere le proprietà ereditate. Questo può diventare un problema se stai analizzando JSON da una fonte non attendibile (es. Un utente) e chiamando su di esso funzioni che ti aspetteresti esistano.
Sfrutta la funzione di tentativo di Lodash per restituire un oggetto errore, che puoi gestire con la funzione 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
invece di usare semplicemente _.attempt (JSON.parse, str)
Assicurati sempre di usare JSON.parse in try catch block poiché il nodo genera sempre un errore imprevisto se hai dei dati danneggiati nel tuo json, quindi usa questo codice invece del semplice JSON.Parse
try{
JSON.parse(data)
}
catch(e){
throw new Error("data is corrupted")
}
Se si desidera aggiungere alcuni commenti nel proprio JSON e consentire le virgole finali si consiglia di utilizzare di seguito l'implementazione:
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);
}
Nota che potrebbe non funzionare bene se hai qualcosa di simile "abc": "foo // bar"
nel tuo JSON. Quindi YMMV.
Se il file sorgente JSON è piuttosto grande, è possibile prendere in considerazione la route asincrona tramite l'approccio asincrono / attesa nativo con Node.js 8.0 come segue
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))
Uso fs-extra . Mi piace molto perché, anche se supporta i callback, supporta anche le promesse . Quindi mi permette solo di scrivere il mio codice in un modo molto più leggibile:
const fs = require('fs-extra');
fs.readJson("path/to/foo.json").then(obj => {
//Do dome stuff with obj
})
.catch(err => {
console.error(err);
});
Ha anche molti metodi utili che non sono associati al fs
modulo standard e , inoltre , fs
collega anche i metodi dal modulo nativo e li promuove.
NOTA: è ancora possibile utilizzare i metodi nativi Node.js. Sono promessi e copiati su fs-extra. Vedi note su
fs.read()
&fs.write()
Quindi sono sostanzialmente tutti i vantaggi. Spero che altri lo trovino utile.
Se è necessario analizzare JSON con Node.js in modo sicuro (ovvero l'utente può inserire dati o un'API pubblica), suggerirei di utilizzare secure-json-parse .
L'utilizzo è come quello predefinito JSON.parse
ma proteggerà il tuo codice da:
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
Puoi usare JSON.parse () (che è una funzione integrata che probabilmente ti costringerà a racchiuderlo con istruzioni try-catch).
Oppure usa una libreria npm di analisi JSON, qualcosa come json-parse-or
Usa questo per essere al sicuro
var data = JSON.parse(Buffer.concat(arr).toString());
NodeJs è un server basato su JavaScript , quindi puoi farlo in puro JavaScript ...
Immagina di avere questo Json in NodeJs ...
var details = '{ "name": "Alireza Dezfoolian", "netWorth": "$0" }';
var obj = JSON.parse(details);
E puoi fare sopra per ottenere una versione analizzata del tuo json ...
Come menzionato nelle risposte sopra, possiamo usare JSON.parse()
per analizzare le stringhe in JSON Ma prima di analizzare, assicurati di analizzare i dati corretti altrimenti potrebbe portare giù l'intera applicazione
è sicuro usarlo in questo modo
let parsedObj = {}
try {
parsedObj = JSON.parse(data);
} catch(e) {
console.log("Cannot parse because data is not is proper json format")
}
Usa JSON.parse(str);
. Leggi di più qui .
Ecco alcuni esempi:
var jsonStr = '{"result":true, "count":42}';
obj = JSON.parse(jsonStr);
console.log(obj.count); // expected output: 42
console.log(obj.result); // expected output: true
È semplice, puoi convertire JSON in string usando JSON.stringify(json_obj)
e convertire string in JSON usando JSON.parse("your json string")
.