Como devo analisar o JSON usando o Node.js? Existe algum módulo que validará e analisará o JSON com segurança?
Como devo analisar o JSON usando o Node.js? Existe algum módulo que validará e analisará o JSON com segurança?
Respostas:
Você pode simplesmente usar JSON.parse
.
A definição do JSON
objeto faz parte da especificação do ECMAScript 5 . O node.js foi criado no mecanismo V8 do Google Chrome , que segue o padrão ECMA. Portanto, o node.js também possui um objeto global [docs] .JSON
Nota - JSON.parse
pode amarrar o segmento atual porque é um método síncrono. Portanto, se você estiver planejando analisar objetos JSON grandes, use um analisador json de streaming.
você pode exigir arquivos .json.
var parsedJSON = require('./file-name');
Por exemplo, se você tiver um config.json
arquivo no mesmo diretório do seu arquivo de código-fonte, você usaria:
var config = require('./config.json');
ou (a extensão do arquivo pode ser omitida):
var config = require('./config');
observe que require
é síncrono e lê o arquivo apenas uma vez ; as chamadas a seguir retornam o resultado do cache
Observe também que você só deve usar isso para arquivos locais sob seu controle absoluto, pois ele potencialmente executa qualquer código dentro do arquivo.
require
é síncrono. Se você deseja sincronizar o uso amigável fs.readFile
comJSON.parse
.json
extensão! Se o seu arquivo NÃO tiver a .json
extensão, o request não o tratará como um arquivo json.
Você pode usarJSON.parse()
.
Você deve poder usar o JSON
objeto em qualquer implementação JavaScript compatível com ECMAScript 5 . E a V8 , na qual o Node.js é construído, é um deles.
Nota: Se você estiver usando um arquivo JSON para armazenar informações confidenciais (por exemplo, senhas), essa é a maneira errada de fazê-lo. Veja como o Heroku faz isso: https://devcenter.heroku.com/articles/config-vars#setting-up-config-vars-for-a-deployed-application . Descubra como sua plataforma faz isso e use
process.env
para recuperar os vars de configuração de dentro do código.
var str = '{ "name": "John Doe", "age": 42 }';
var obj = JSON.parse(str);
Você terá que fazer algumas operações de arquivo com o 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
? Pense de novo!Às vezes você pode usarrequire
:
var obj = require('path/to/file.json');
Mas, eu não recomendo isso por vários motivos:
require
é síncrono. Se você tiver um arquivo JSON muito grande, ele bloqueará seu loop de eventos. Você realmente precisa usar JSON.parse
com fs.readFile
.require
irá ler o arquivo apenas uma vez . As chamadas subseqüentes require
para o mesmo arquivo retornarão uma cópia em cache. Não é uma boa ideia se você deseja ler um .json
arquivo que é atualizado continuamente. Você pode usar um hack . Mas, neste ponto, é mais fácil simplesmente usar fs
..json
extensão, require
não tratará o conteúdo do arquivo como JSON.A sério! UseJSON.parse
.
load-json-file
móduloSe você está lendo um grande número de .json
arquivos (e se você é extremamente preguiçoso), torna-se irritante escrever código padrão sempre. Você pode salvar alguns caracteres usando o 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');
Se o conteúdo JSON for transmitido pela rede, você precisará usar um analisador JSON de streaming. Caso contrário, ele amarrará seu processador e bloqueará seu loop de eventos até que o conteúdo JSON seja totalmente transmitido.
Existem muitos pacotes disponíveis no NPM para isso. Escolha o que é melhor para você.
Se você não tiver certeza se o que foi transmitido JSON.parse()
é JSON válido , certifique-se de incluir a chamada JSON.parse()
dentro de um try/catch
bloco. Um usuário que forneceu uma string JSON pode travar seu aplicativo e até levar a falhas de segurança. Certifique-se de que a manipulação de erros seja realizada se você analisar o JSON fornecido externamente.
and could even lead to security holes
por curiosidade, como?
<script>...
e o erro foi derramado no lado do cliente, você tem um bug do XSS ali. Portanto, o IMO é importante para lidar com erros JSON exatamente onde você os analisa.
require
para incluir JSON?" e nem se deu ao trabalho de documentar os efeitos colaterais. Isso também significava que exigir aceita arquivos em dois idiomas: JavaScript e JSON (não, eles não são os mesmos). Tanta coisa para SRP.
use o objeto JSON :
JSON.parse(str);
Outro exemplo 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);
});
Eu gostaria de mencionar que existem alternativas para o objeto JSON global.
JSON.parse
e JSON.stringify
são síncronos; portanto, se você deseja lidar com grandes objetos, consulte alguns dos módulos JSON assíncronos.
Dê uma olhada: https://github.com/joyent/node/wiki/Modules#wiki-parsers-json
JSON.parse
todo o aplicativo falhar ou, usando-o process.on('uncaughtException', function(err) { ... });
, não haverá chance de enviar um erro "JSON malformado" ao usuário.
async
analisador? Eu não encontrei isso.
Inclua a node-fs
biblioteca.
var fs = require("fs");
var file = JSON.parse(fs.readFileSync("./PATH/data.json", "utf8"));
Para mais informações sobre a biblioteca 'fs', consulte a documentação em http://nodejs.org/api/fs.html
Como você não sabe que sua string é realmente válida, eu a colocaria primeiro em uma tentativa. Além disso, como os blocos try catch não são otimizados por nó, eu colocaria a coisa inteira em outra função:
function tryParseJson(str) {
try {
return JSON.parse(str);
} catch (ex) {
return null;
}
}
OU no "estilo assíncrono"
function tryParseJson(str, callback) {
process.nextTick(function () {
try {
callback(null, JSON.parse(str));
} catch (ex) {
callback(ex)
}
})
}
Analisando um fluxo JSON? Use 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 mundo aqui falou sobre JSON.parse, então pensei em dizer outra coisa. Há um ótimo módulo Conecte-se a muitos middlewares para facilitar e melhorar o desenvolvimento de aplicativos. Um dos middlewares é o bodyParser . Ele analisa JSON, html-forms e etc. Há também um middleware específico para JSON que analisa apenas noop .
Dê uma olhada nos links acima, pode ser realmente útil para você.
JSON.parse("your string");
Isso é tudo.
como outras respostas mencionadas aqui, você provavelmente deseja exigir um arquivo json local que você sabe que é seguro e presente, como um arquivo de configuração:
var objectFromRequire = require('path/to/my/config.json');
ou para usar o objeto JSON global para analisar um valor de sequência em um objeto:
var stringContainingJson = '\"json that is obtained from somewhere\"';
var objectFromParse = JSON.parse(stringContainingJson);
Observe que, quando você exige um arquivo, o conteúdo desse arquivo é avaliado, o que apresenta um risco à segurança, caso não seja um arquivo json, mas um arquivo js.
publiquei uma demonstração em que é possível ver os dois métodos e jogar com eles on-line (o exemplo de análise está no arquivo app.js - clique no botão executar e veja o resultado no terminal): http: // staging1 .codefresh.io / labs / api / env / json-parse-example
você pode modificar o código e ver o impacto ...
Usando JSON para sua configuração com o Node.js? Leia isso e obtenha suas habilidades de configuração acima de 9000 ...
Nota: Pessoas que afirmam que dados = require ('./ data.json'); é um risco à segurança e rebate as respostas das pessoas com zelo zeloso: você está exatamente e completamente errado . Experimente colocar não-JSON naquele arquivo ... Nó lhe dará um erro, exatamente como seria se você fez a mesma coisa com o muito mais lento e mais difícil de código de leitura de arquivo manual e, em seguida, posterior JSON.parse (). Por favor, pare de espalhar informações erradas; você está machucando o mundo, não está ajudando. O nó foi projetado para permitir isso; não é um risco à segurança!
Os aplicativos adequados vêm em mais de 3 camadas de configuração:
A maioria dos desenvolvedores trata suas configurações de servidor e aplicativo como se isso pudesse mudar. Não pode. Você pode colocar as alterações das camadas superiores umas sobre as outras, mas está modificando os requisitos básicos . Algumas coisas precisam existir! Faça sua configuração agir como se fosse imutável, porque parte disso é basicamente como o seu código-fonte.
Não perceber que muitas das suas coisas não serão alteradas após a inicialização leva a antipadrões, como desarrumar o carregamento da sua configuração com blocos try / catch e fingir que você pode continuar sem o aplicativo de configuração adequado. Você não pode. Se possível, isso pertence à camada de configuração da comunidade / usuário, não à camada de configuração do servidor / aplicativo. Você está fazendo errado. O material opcional deve ser colocado em camadas quando o aplicativo terminar sua inicialização.
Pare de bater com a cabeça na parede: sua configuração deve ser extremamente simples .
Veja como é fácil configurar algo tão complexo quanto uma estrutura de serviço independente de protocolo e independente de fonte de dados usando um arquivo json config simples e um arquivo app.js simples ...
container-config.js ...
{
"service": {
"type" : "http",
"name" : "login",
"port" : 8085
},
"data": {
"type" : "mysql",
"host" : "localhost",
"user" : "notRoot",
"pass" : "oober1337",
"name" : "connect"
}
}
index.js ... (o mecanismo que alimenta tudo)
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 ... (o código que alimenta seu serviço independente de protocolo e de origem de dados)
module.exports = function(request, response){
response.end('Responding to: ' + request.url);
}
Usando esse padrão, agora você pode carregar itens de configuração da comunidade e do usuário sobre o aplicativo inicializado, o dev ops está pronto para colocar seu trabalho em um contêiner e escalá-lo. Você é lido para vários participantes. Userland é isolado. Agora você pode separar as preocupações sobre qual protocolo de serviço você está usando, qual tipo de banco de dados você está usando e se concentrar apenas em escrever um bom código.
Como você está usando camadas, pode confiar em uma única fonte de verdade para tudo, a qualquer momento (o objeto de configuração em camadas) e evitar verificações de erro a cada passo, preocupando-se com "oh droga, como vou fazer isso trabalhar sem a configuração adequada?!? ".
Minha solução:
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
erros - alguma idéia de onde começar a depurar esse problema?
Só quero completar a resposta (como eu lutei com ela por um tempo), quero mostrar como acessar as informações do json, este exemplo mostra como acessar o 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);
}
})
Apenas para tornar isso o mais complicado possível e trazer o maior número possível de pacotes ...
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);
Isso permite que você faça:
var dataPromise = readJsonFile("foo.json");
dataPromise.then(console.log);
Ou se você estiver usando async / waitit:
let data = await readJsonFile("foo.json");
A vantagem de apenas usar readFileSync
é que o servidor Node pode processar outras solicitações enquanto o arquivo está sendo lido no disco.
O JSON.parse não garantirá a segurança da string json que você está analisando. Você deve olhar para uma biblioteca como json-safe-parse ou uma biblioteca semelhante.
Na página json-safe-parse npm:
O JSON.parse é ótimo, mas possui uma falha séria no contexto do JavaScript: permite substituir propriedades herdadas. Isso pode se tornar um problema se você estiver analisando o JSON de uma fonte não confiável (por exemplo: um usuário) e chamando funções nele que você espera que exista.
Utilize a função de tentativa do Lodash para retornar um objeto de erro, que você pode manipular com a função 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
ao invés de apenas usar _.attempt (JSON.parse, str)
Sempre certifique-se de usar JSON.parse em try catch block, pois o nó sempre gera um erro inesperado se você tiver alguns dados corrompidos em seu json; portanto, use esse código em vez de JSON.Parse simples
try{
JSON.parse(data)
}
catch(e){
throw new Error("data is corrupted")
}
Se você quiser adicionar alguns comentários no seu JSON e permitir vírgulas finais, use a implementação abaixo:
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);
}
Observe que pode não funcionar bem se você tiver algo parecido "abc": "foo // bar"
no seu JSON. Então YMMV.
Se o arquivo de origem JSON for muito grande, convém considerar a rota assíncrona por meio da abordagem nativa async / waitit com o Node.js. 8.0 da seguinte maneira
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))
Eu uso fs-extra . Gosto muito porque, apesar de suportar retornos de chamada, também oferece suporte a Promises . Por isso, apenas me permite escrever meu código de uma maneira muito mais legível:
const fs = require('fs-extra');
fs.readJson("path/to/foo.json").then(obj => {
//Do dome stuff with obj
})
.catch(err => {
console.error(err);
});
Ele também possui muitos métodos úteis que não acompanham o fs
módulo padrão e , além disso, também faz a ponte dos métodos do fs
módulo nativo e os promete.
NOTA: Você ainda pode usar os métodos nativos do Node.js. Eles são promissificados e copiados para o fs-extra. Veja notas sobre
fs.read()
&fs.write()
Então é basicamente todas as vantagens. Espero que outros achem isso útil.
Se você precisar analisar JSON com Node.js de maneira segura (ou seja: o usuário pode inserir dados ou uma API pública), sugiro usar secure-json-parse .
O uso é como o padrão, JSON.parse
mas protegerá seu 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
Você pode usar JSON.parse () (que é uma função interna que provavelmente o forçará a envolvê-lo com instruções try-catch).
Ou use alguma biblioteca npm de análise JSON, algo como json-parse-or
Use isso para estar do lado seguro
var data = JSON.parse(Buffer.concat(arr).toString());
O NodeJs é um servidor baseado em JavaScript , para que você possa fazer isso em JavaScript puro ...
Imagine que você tem esse Json em NodeJs ...
var details = '{ "name": "Alireza Dezfoolian", "netWorth": "$0" }';
var obj = JSON.parse(details);
E você pode fazer acima para obter uma versão analisada do seu json ...
Conforme mencionado nas respostas acima, podemos usar JSON.parse()
para analisar as seqüências de caracteres em JSON. Antes de analisar, certifique-se de analisar os dados corretos, caso contrário, poderá interromper o aplicativo inteiro
é seguro usá-lo assim
let parsedObj = {}
try {
parsedObj = JSON.parse(data);
} catch(e) {
console.log("Cannot parse because data is not is proper json format")
}
Use JSON.parse(str);
. Leia mais sobre isso aqui .
aqui estão alguns exemplos:
var jsonStr = '{"result":true, "count":42}';
obj = JSON.parse(jsonStr);
console.log(obj.count); // expected output: 42
console.log(obj.result); // expected output: true
É simples, você pode converter JSON em string usando JSON.stringify(json_obj)
e converter string em JSON usando JSON.parse("your json string")
.