javascript - ¿Cómo analizar JSON usando Node.js?
(29)
Analizar un flujo JSON? Utilice 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
}))
¿Cómo debo analizar JSON utilizando Node.js? ¿Hay algún módulo que valide y analice JSON de forma segura?
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
Como han mencionado otras respuestas aquí, es probable que desee solicitar un archivo json local que sepa que es seguro y está 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 presenta un riesgo de seguridad en caso de que no sea un archivo json, sino un archivo js.
Aquí, he publicado una demostración donde 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 ...
Es simple, puede convertir JSON a cadena usando JSON.stringify(json_obj)
, y convertir cadena a JSON usando JSON.parse("your json string")
.
Esto tenía que .json
: solo funciona para archivos .json
.
Si el final del archivo es diferente, ¡esto no funciona!
Incluye la biblioteca node-fs
.
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
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.
De la página npm de json-safe-parse:
JSON.parse es genial, pero tiene un defecto 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 si llama a funciones en él que esperaría que existieran.
Me gustaría mencionar que hay alternativas al objeto JSON global. JSON.parse
y JSON.stringify
son síncronos, por lo que si desea tratar objetos grandes, es posible que desee revisar algunos de los módulos JSON asíncronos.
Eche un vistazo: https://github.com/joyent/node/wiki/Modules#wiki-parsers-json
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);
});
No se necesitan más módulos.
Solo usa
var parsedObj = JSON.parse(yourObj);
No creo que haya ningún problema de seguridad con respecto a esto
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);
});
Puede usar JSON.parse () (que es una función incorporada que probablemente lo obligará a envolverlo con declaraciones try-catch).
O use alguna biblioteca JSON para analizar npm, algo como json-parse-or
Si desea agregar algunos comentarios en su JSON y permitir comas finales, es posible que desee utilizarlos debajo de la 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 puede que no funcione bien si tiene algo como "abc": "foo // bar"
en su JSON. Así que YMMV.
Si el archivo fuente JSON es bastante grande, es posible que desee considerar la ruta asíncrona a través del enfoque nativo async / await 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))
Siempre asegúrese de usar JSON.parse en el bloque try catch , ya que el nodo siempre genera un error inesperado si tiene algunos datos dañados en su json, así que use este código en lugar del simple JSON.Parse
try{
JSON.parse(data)
}
catch(e){
throw new Error("data is corrupted")
}
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ás usando async / await:
let data = await readJsonFile("foo.json");
La ventaja sobre el simple uso de readFileSync
es que su servidor Node puede procesar otras solicitudes mientras el archivo se lee en el disco.
Solo quiero completar la respuesta (mientras luché con ella por un tiempo), quiero mostrar cómo acceder a la información de 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);
}
})
Todo el mundo aquí ha hablado de JSON.parse, así que pensé en decir algo más. Hay un gran módulo Connect con muchos middleware para facilitar y mejorar el desarrollo de aplicaciones. Uno de los middleware es bodyParser . Analiza JSON, html-forms y etc. También hay un middleware específico para JSON que analiza solo noop .
Eche un vistazo a los enlaces de arriba, puede ser de gran ayuda para usted.
Use esto para estar en el lado seguro
var data = JSON.parse (Buffer.concat (arr) .toString ());
Utilice JSON.parse (str);
saber más - JSON.parse
ejemplo
var jsonStr = ''{"result":true, "count":42}'';
obj = JSON.parse(jsonStr);
console.log(obj.count); //expected output: 42
console.log(obj.result); // expected output: true
Ya que no sabes que tu cadena es realmente válida, la pondría primero en una captura de prueba. 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)
}
})
}
puede require archivos .json.
var parsedJSON = require(''./file-name'');
Por ejemplo, si tiene un archivo config.json
en el mismo directorio que el archivo de código fuente que usaría:
var config = require(''./config.json'');
o (la extensión del archivo se puede omitir):
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é
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.
usar el objeto JSON :
JSON.parse(str);
¿Usando JSON para su configuración con Node.js? Lea esto y obtenga sus habilidades de configuración más de 9000 ...
Nota: las personas que afirman que data = require (''./ data.json''); es un riesgo para la seguridad y la reducción de las respuestas de las personas con fervor celo: estás equivocada de manera exacta y total. Intente colocar un archivo no JSON en ese archivo ... Node le dará un error, exactamente como lo haría si hiciera lo mismo con la lectura del archivo del manual, mucho más lenta y más difícil, y luego el archivo JSON.parse (). Por favor, deja de difundir la desinformación; Estás lastimando al mundo, no ayudando. El nodo 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:
- Configuración del servidor / contenedor
- Configuración de la aplicación
- (Opcional) Configuración de inquilino / comunidad / organización
- Configuración de usuario
La mayoría de los desarrolladores tratan su configuración de servidor y aplicación como si pudiera cambiar. No puede Puede colocar cambios de capas superiores uno encima de otro, 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 es básicamente, al igual que su código fuente.
Si no ve que muchas de sus cosas no van a cambiar después de la puesta en marcha, se pueden crear patrones como ensuciar la configuración de su carga con los bloques try / catch y pretender que puede continuar sin la aplicación de configuración adecuada. Usted no puede Si puede, eso pertenece a la capa de configuración de la comunidad / usuario, no a la capa de configuración del servidor / aplicación. Lo estás haciendo mal. Las cosas opcionales deben colocarse en la parte superior cuando la aplicación termina su bootstrap.
Deja de golpear tu 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 servicios independiente del protocolo y del origen de datos utilizando un simple archivo de configuración json y un archivo simple 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 ... (el motor que lo potencia 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 potencia su servicio independiente de protocolo y fuente de datos)
module.exports = function(request, response){
response.end(''Responding to: '' + request.url);
}
Usando este patrón, ahora puedes cargar cosas de configuración de la comunidad y del usuario en la parte superior de la aplicación iniciada, las operaciones dev están listas para meter tu trabajo en un contenedor y escalarlo. Eres leído para multitenant. Userland está aislado. Ahora puede separar las preocupaciones de qué protocolo de servicio está utilizando, qué tipo de base de datos está utilizando y simplemente concentrarse 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 las comprobaciones de errores en cada paso, preocupándose por "oh mierda, ¿cómo voy a hacer esto?" trabajar sin la configuración adecuada?!? ".
Puedes usar JSON.parse .
Debería poder usar el objeto JSON
en cualquier implementación de JavaScript compatible con ECMAScript 5 . Y V8 , sobre el cual se construye Node.js es uno de ellos.
Analizar una cadena que contiene datos JSON
var str = ''{ "name": "John Doe", "age": 42 }'';
var obj = JSON.parse(str);
Analizar un archivo que contiene datos JSON
Tendrás que hacer algunas operaciones de archivo con el módulo fs
.
Versión asíncrona
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);
});
Versión síncrona
var fs = require(''fs'');
var json = JSON.parse(fs.readFileSync(''/path/to/file.json'', ''utf8''));
¿Quieres usar require
? ¡Piensa otra vez!
A veces se puede utilizar require
:
var obj = require(''path/to/file.json'');
Pero, no lo recomiendo por varias razones:
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 . Averigüe cómo lo hace su plataforma y use
process.env
para recuperar los parámetros de configuración desde el código.
-
require
es síncrono. Si tiene un archivo JSON muy grande, estrangulará su bucle de eventos. Realmente necesitas usarJSON.parse
confs.readFile
. -
require
leerá el archivo una sola vez . Las llamadas posteriores que serequire
para el mismo archivo devolverán una copia en caché. No es una buena idea si desea leer un archivo.json
que se actualiza continuamente. Podrías usar un hack . Pero en este punto, es más fácil simplemente usarfs
. - Si su archivo no tiene una extensión
.json
,require
no tratará el contenido del archivo como JSON.
¡Seriamente! Utilice JSON.parse
.
módulo load-json-file
Si estás leyendo una gran cantidad de archivos .json
(y si eres muy perezoso), se vuelve molesto escribir código repetitivo cada vez. Puede guardar algunos caracteres utilizando el módulo load-json-file
.
const loadJsonFile = require(''load-json-file'');
Versión asíncrona
loadJsonFile(''/path/to/file.json'').then(json => {
// `json` contains the parsed object
});
Versión síncrona
let obj = loadJsonFile.sync(''/path/to/file.json'');
Analizando JSON desde arroyos
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 completamente.
Hay muchos paquetes disponibles en NPM para esto. Elige lo que es mejor para ti.
Manejo de errores / seguridad
Si no está seguro de si lo que se pasa a JSON.parse()
es JSON válido , asegúrese de incluir la llamada a JSON.parse()
dentro de un bloque try/catch
. Una cadena JSON provista 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.
Simplemente puede utilizar JSON.parse
.
La definición del objeto JSON
es parte de la especificación ECMAScript 5 . node.js se basa en el motor V8 Google Chrome, que cumple con el estándar ECMA. Por lo tanto, node.js también tiene un objeto global JSON[docs] .
Nota: JSON.parse
puede atar el hilo actual porque es un método síncrono. Por lo tanto, si planea analizar grandes objetos JSON, use un analizador json de transmisión.
JSON.parse("your string");
Eso es todo.
var array={
Action: ''Login'',
ErrorCode: 3,
Detail: ''Your account not found.''
};
var http=require(''http''),
PORT=8789,
server=function(req,res){
res.writeHead(200,{''Content-Type'':''application/json''});
// JSON
res.end(JSON.stringify(array));
}
http.createServer(server).listen(PORT);
console.log(''Server started.'');
var fs = require(''fs'');
fs.readFile(''ashish.json'',{encoding:''utf8''},function(data,err) {
if(err)
throw err;
else {
console.log(data.toString());
}
})