¿Cómo debería analizar JSON usando Node.js? ¿Hay algún módulo que valide y analice JSON de forma segura?
¿Cómo debería analizar JSON usando Node.js? ¿Hay algún módulo que valide y analice JSON de forma segura?
Respuestas:
Puedes simplemente usar JSON.parse
.
La definición del JSON
objeto es parte de la especificación ECMAScript 5 . node.js se basa en el motor V8 de Google Chrome , que se adhiere al estándar ECMA. Por lo tanto, node.js también tiene un objeto global [docs] .JSON
Nota: JSON.parse
puede atar el hilo actual porque es un método sincrónico. Entonces, si planea analizar grandes objetos JSON, use un analizador de json de transmisión.
puede requerir archivos .json.
var parsedJSON = require('./file-name');
Por ejemplo, si tiene un config.json
archivo en el mismo directorio que su archivo de código fuente, usaría:
var config = require('./config.json');
o (se puede omitir la extensión del archivo):
var config = require('./config');
tenga en cuenta que require
es sincrónico y solo lee el archivo una vez , las siguientes llamadas devuelven el resultado del caché
También tenga en cuenta que solo debe usar esto para archivos locales bajo su control absoluto, ya que potencialmente ejecuta cualquier código dentro del archivo.
require
es sincrónico. Si quieres asíncrono uso amigable fs.readFile
conJSON.parse
.json
extensión! Si su archivo NO tiene la .json
extensión, require no lo tratará como un archivo json.
Puedes usarJSON.parse()
.
Debería poder utilizar el JSON
objeto en cualquier implementación de JavaScript compatible con ECMAScript 5 . Y V8 , sobre el cual se construye Node.js, es uno de ellos.
Nota: Si está utilizando un archivo JSON para almacenar información confidencial (por ejemplo, contraseñas), esa es la forma incorrecta de hacerlo. Vea cómo lo hace Heroku: https://devcenter.heroku.com/articles/config-vars#setting-up-config-vars-for-a-deployed-application . Descubra cómo lo hace su plataforma y úsela
process.env
para recuperar los valores de configuración desde el código.
var str = '{ "name": "John Doe", "age": 42 }';
var obj = JSON.parse(str);
Tendrás que hacer algunas operaciones de archivo con el fs
módulo.
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
? ¡Piensa otra vez!var obj = require('path/to/file.json');
Pero no recomiendo esto por varias razones:
require
es sincrónico Si tiene un archivo JSON muy grande, ahogará su bucle de eventos. Realmente necesitas usar JSON.parse
con fs.readFile
.require
leerá el archivo solo una vez . Las llamadas posteriores al require
mismo archivo devolverán una copia en caché. No es una buena idea si desea leer un .json
archivo que se actualiza continuamente. Podrías usar un truco . Pero en este punto, es más fácil de usar fs
..json
extensión, require
no tratará el contenido del archivo como JSON.¡Seriamente! UsoJSON.parse
.
load-json-file
móduloSi está leyendo una gran cantidad de .json
archivos (y si es extremadamente vago), se vuelve molesto escribir código repetitivo cada vez. Puede guardar algunos caracteres usando el load-json-file
módulo.
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');
Si el contenido JSON se transmite a través de la red, debe usar un analizador JSON de transmisión. De lo contrario, atará su procesador y estrangulará su bucle de eventos hasta que el contenido JSON se transmita por completo.
Hay muchos paquetes disponibles en NPM para esto. Elige lo que sea mejor para ti.
Si no está seguro de si lo que se le pasa JSON.parse()
es JSON válido , asegúrese de encerrar la llamada JSON.parse()
dentro de un try/catch
bloque. Una cadena JSON proporcionada por el usuario podría bloquear su aplicación e incluso podría generar agujeros de seguridad. Asegúrese de que el manejo de errores se realiza si analiza JSON proporcionado externamente.
and could even lead to security holes
por curiosidad, ¿cómo?
<script>...
, y el error se derramó en el lado del cliente, tiene un error XSS allí mismo. Por lo tanto, es importante manejar los errores JSON justo donde lo analiza.
require
para incluir a JSON?" y ni siquiera se molestó en documentar los efectos secundarios. Esto también significa que requiere aceptar archivos en dos idiomas: JavaScript y JSON (no, no son lo mismo). Demasiado para SRP.
usa el objeto JSON :
JSON.parse(str);
Otro ejemplo de 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);
});
Me gustaría mencionar que hay alternativas al objeto JSON global.
JSON.parse
y JSON.stringify
ambos son síncronos, por lo que si desea tratar con objetos grandes, es posible que desee consultar algunos de los módulos JSON asíncronos.
Echa un vistazo: https://github.com/joyent/node/wiki/Modules#wiki-parsers-json
JSON.parse
toda la aplicación analiza el JSON con formato incorrecto, se bloqueará o, al usarlo process.on('uncaughtException', function(err) { ... });
, eventualmente no habrá posibilidad de enviar un error de "JSON con formato incorrecto" al usuario.
async
analizador sintáctico? No lo encontré.
Incluye la node-fs
biblioteca.
var fs = require("fs");
var file = JSON.parse(fs.readFileSync("./PATH/data.json", "utf8"));
Para obtener más información sobre la biblioteca 'fs', consulte la documentación en http://nodejs.org/api/fs.html
Como no sabe que su cadena es realmente válida, la pondría primero en un intento de captura. Además, dado que los bloques try catch no están optimizados por nodo, pondría todo en otra función:
function tryParseJson(str) {
try {
return JSON.parse(str);
} catch (ex) {
return null;
}
}
O en "estilo asíncrono"
function tryParseJson(str, callback) {
process.nextTick(function () {
try {
callback(null, JSON.parse(str));
} catch (ex) {
callback(ex)
}
})
}
Analizando una secuencia JSON? Uso 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
}))
Todo el mundo aquí ha contado sobre JSON.parse, así que pensé en decir algo más. Hay un gran módulo Conéctese con muchos middleware para hacer que el desarrollo de aplicaciones sea más fácil y mejor. Uno de los middleware es bodyParser . Analiza JSON, formularios html, etc. También hay un middleware específico para JSON que analiza solo noop .
Eche un vistazo a los enlaces de arriba, podría ser realmente útil para usted.
JSON.parse("your string");
Eso es todo.
Como han mencionado otras respuestas aquí, probablemente desee solicitar un archivo json local que sepa que es seguro y presente, como un archivo de configuración:
var objectFromRequire = require('path/to/my/config.json');
o para usar el objeto JSON global para analizar un valor de cadena en un objeto:
var stringContainingJson = '\"json that is obtained from somewhere\"';
var objectFromParse = JSON.parse(stringContainingJson);
tenga en cuenta que cuando necesita un archivo, se evalúa el contenido de ese archivo, lo que introduce un riesgo de seguridad en caso de que no sea un archivo json sino un archivo js.
aquí, publiqué una demostración en la que puede ver ambos métodos y jugar con ellos en línea (el ejemplo de análisis está en el archivo app.js, luego haga clic en el botón Ejecutar y vea el resultado en el terminal): http: // staging1 .codefresh.io / labs / api / env / json-parse-example
puedes modificar el código y ver el impacto ...
¿Usa JSON para su configuración con Node.js? Lea esto y obtenga sus habilidades de configuración por encima de 9000 ...
Nota: Las personas que afirman que data = require ('./ data.json'); es un riesgo para la seguridad y rechazar las respuestas de las personas con celo celoso: estás exactamente y completamente equivocado . Intente colocar no JSON en ese archivo ... Node le dará un error, exactamente como lo haría si hiciera lo mismo con la lectura de archivos manual mucho más lenta y difícil de codificar y luego JSON.parse (). Por favor, deje de difundir información errónea; estás lastimando al mundo, no ayudando. Node fue diseñado para permitir esto; ¡No es un riesgo de seguridad!
Las aplicaciones adecuadas vienen en más de 3 capas de configuración:
La mayoría de los desarrolladores tratan la configuración de su servidor y aplicación como si pudiera cambiar. No puede Puede superponer cambios de capas superiores una encima de otra, pero está modificando los requisitos básicos . ¡Algunas cosas necesitan existir! Haga que su configuración actúe como si fuera inmutable, porque parte de ella básicamente lo es, al igual que su código fuente.
No ver que muchas de sus cosas no van a cambiar después del inicio conduce a antipatrones como ensuciar su carga de configuración con bloques try / catch y pretender que puede continuar sin su aplicación de configuración adecuada. No puedes Si puede, eso pertenece a la capa de configuración de comunidad / usuario, no a la capa de configuración de servidor / aplicación. Solo lo estás haciendo mal. Las cosas opcionales deben colocarse en capas en la parte superior cuando la aplicación finalice su arranque.
Deja de golpearte la cabeza contra la pared: tu configuración debe ser ultra simple .
Eche un vistazo a lo fácil que es configurar algo tan complejo como un marco de servicio independiente del protocolo y del origen de datos utilizando un archivo de configuración json simple y un archivo app.js simple ...
container-config.js ...
{
"service": {
"type" : "http",
"name" : "login",
"port" : 8085
},
"data": {
"type" : "mysql",
"host" : "localhost",
"user" : "notRoot",
"pass" : "oober1337",
"name" : "connect"
}
}
index.js ... (el motor que impulsa todo)
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 ... (el código que impulsa su servicio independiente de protocolo y fuente de datos)
module.exports = function(request, response){
response.end('Responding to: ' + request.url);
}
Con este patrón, ahora puede cargar cosas de configuración de la comunidad y del usuario en la parte superior de su aplicación arrancada, las operaciones de desarrollo están listas para llevar su trabajo a un contenedor y escalarlo. Estás leído para multiempresa. Userland está aislado. Ahora puede separar las preocupaciones de qué protocolo de servicio está usando, qué tipo de base de datos está usando, y simplemente centrarse en escribir un buen código.
Debido a que está utilizando capas, puede confiar en una única fuente de verdad para todo, en cualquier momento (el objeto de configuración en capas) y evitar verificaciones de errores en cada paso, preocupándose por "oh mierda, ¿cómo voy a hacer esto? funciona sin la configuración adecuada?!? ".
Mi solución:
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
errores. ¿ Alguna idea de dónde comenzar a depurar este problema?
Solo quiero completar la respuesta (mientras luché con ella por un tiempo), quiero mostrar cómo acceder a la información json, este ejemplo muestra cómo acceder 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 para hacer esto lo más complicado posible, y traer tantos paquetes como sea posible ...
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);
Esto te permite hacer:
var dataPromise = readJsonFile("foo.json");
dataPromise.then(console.log);
O si está utilizando async / await:
let data = await readJsonFile("foo.json");
La ventaja sobre el uso readFileSync
es que su servidor Node puede procesar otras solicitudes mientras el archivo se lee desde el disco.
JSON.parse no garantizará la seguridad de la cadena json que está analizando. Debería mirar una biblioteca como json-safe-parse o una biblioteca similar.
Desde la página nson json-safe-parse:
JSON.parse es excelente, pero tiene una falla grave en el contexto de JavaScript: le permite anular las propiedades heredadas. Esto puede convertirse en un problema si está analizando JSON desde una fuente no confiable (por ejemplo: un usuario), y llamando a funciones que esperaría que existieran.
Aproveche la función de intento de Lodash para devolver un objeto de error, que puede manejar con la función 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
lugar de simplemente usar _.attempt (JSON.parse, str)
Siempre asegúrese de usar JSON.parse en try catch block ya que el nodo siempre arroja un Error inesperado si tiene algunos datos corruptos en su json, así que use este código en lugar de JSON.Parse simple
try{
JSON.parse(data)
}
catch(e){
throw new Error("data is corrupted")
}
Si desea agregar algunos comentarios en su JSON y permitir las comas finales, puede usar la siguiente implementación:
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);
}
Tenga en cuenta que podría no funcionar bien si tiene algo como "abc": "foo // bar"
en su JSON. Entonces YMMV.
Si el archivo fuente JSON es bastante grande, puede considerar la ruta asincrónica a través del enfoque asíncrono / espera nativo con Node.js 8.0 de la siguiente manera
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))
Yo uso fs-extra . Me gusta mucho porque, aunque admite devoluciones de llamada, también admite Promesas . Entonces solo me permite escribir mi código de una manera mucho más legible:
const fs = require('fs-extra');
fs.readJson("path/to/foo.json").then(obj => {
//Do dome stuff with obj
})
.catch(err => {
console.error(err);
});
También tiene muchos métodos útiles que no vienen junto con el fs
módulo estándar y , además de eso, también fs
une los métodos del módulo nativo y los promete.
NOTA: aún puede utilizar los métodos nativos de Node.js. Son prometidos y copiados a fs-extra. Ver notas sobre
fs.read()
&fs.write()
Así que básicamente son todas las ventajas. Espero que otros encuentren esto útil.
Si necesita analizar JSON con Node.js de forma segura (también conocido como: el usuario puede ingresar datos o una API pública), sugeriría usar secure-json-parse .
El uso es el predeterminado, JSON.parse
pero protegerá su código de:
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
Puede usar JSON.parse () (que es una función integrada que probablemente lo obligará a envolverlo con declaraciones try-catch).
O utilice alguna biblioteca npm de análisis JSON, algo como json-parse-or
Use esto para estar seguro
var data = JSON.parse(Buffer.concat(arr).toString());
NodeJs es un servidor basado en JavaScript , por lo que puede hacer lo que hace en JavaScript puro ...
Imagina que tienes este Json en NodeJs ...
var details = '{ "name": "Alireza Dezfoolian", "netWorth": "$0" }';
var obj = JSON.parse(details);
Y puede hacer lo anterior para obtener una versión analizada de su json ...
Como se menciona en las respuestas anteriores, podemos usar JSON.parse()
para analizar las cadenas a JSON. Pero antes de analizar, asegúrese de analizar los datos correctos o de lo contrario podría hacer que su aplicación se caiga.
es seguro usarlo así
let parsedObj = {}
try {
parsedObj = JSON.parse(data);
} catch(e) {
console.log("Cannot parse because data is not is proper json format")
}
Uso JSON.parse(str);
. Lea más sobre esto aquí .
Aquí hay unos ejemplos:
var jsonStr = '{"result":true, "count":42}';
obj = JSON.parse(jsonStr);
console.log(obj.count); // expected output: 42
console.log(obj.result); // expected output: true
Es simple, puede convertir JSON a cadena usando JSON.stringify(json_obj)
, y convertir cadena a JSON usando JSON.parse("your json string")
.