Comment analyser JSON en utilisant Node.js? Existe-t-il un module qui va valider et analyser JSON en toute sécurité?
Comment analyser JSON en utilisant Node.js? Existe-t-il un module qui va valider et analyser JSON en toute sécurité?
Réponses:
Vous pouvez simplement utiliser JSON.parse
.
La définition de l' JSON
objet fait partie de la spécification ECMAScript 5 . node.js est construit sur le moteur V8 de Google Chrome , qui respecte la norme ECMA. Par conséquent, node.js a également un objet global [docs] .JSON
Remarque - JSON.parse
peut bloquer le thread actuel car il s'agit d'une méthode synchrone. Donc, si vous prévoyez d'analyser de gros objets JSON, utilisez un analyseur json en streaming.
vous pouvez exiger des fichiers .json.
var parsedJSON = require('./file-name');
Par exemple, si vous avez un config.json
fichier dans le même répertoire que votre fichier de code source, vous utiliseriez:
var config = require('./config.json');
ou (l'extension de fichier peut être omise):
var config = require('./config');
notez qu'il require
est synchrone et ne lit le fichier qu'une seule fois , les appels suivants renvoient le résultat du cache
Notez également que vous ne devez l'utiliser que pour les fichiers locaux sous votre contrôle absolu, car il exécute potentiellement tout code dans le fichier.
require
c'est synchrone. Si vous souhaitez asynchroniser une utilisation conviviale à la fs.readFile
place avecJSON.parse
.json
extension! Si votre fichier n'a PAS l' .json
extension, require ne le traitera pas comme un fichier json.
Vous pouvez utiliserJSON.parse()
.
Vous devriez pouvoir utiliser l' JSON
objet sur n'importe quelle implémentation JavaScript compatible ECMAScript 5 . Et V8 , sur lequel Node.js est construit, en fait partie.
Remarque: Si vous utilisez un fichier JSON pour stocker des informations sensibles (par exemple des mots de passe), ce n'est pas la bonne façon de le faire. Découvrez comment Heroku le fait: https://devcenter.heroku.com/articles/config-vars#setting-up-config-vars-for-a-deployed-application . Découvrez comment votre plate-forme le fait et utilisez
process.env
pour récupérer les variables de configuration à partir du code.
var str = '{ "name": "John Doe", "age": 42 }';
var obj = JSON.parse(str);
Vous devrez effectuer certaines opérations sur les fichiers avec le fs
module.
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
? Détrompez-vous!Vous pouvez parfois utiliserrequire
:
var obj = require('path/to/file.json');
Mais, je ne le recommande pas pour plusieurs raisons:
require
est synchrone. Si vous avez un très gros fichier JSON, il étouffera votre boucle d'événements. Vous devez vraiment l'utiliser JSON.parse
avec fs.readFile
.require
ne lira le fichier qu'une seule fois . Les appels suivants à require
pour le même fichier renverront une copie mise en cache. Ce n'est pas une bonne idée si vous souhaitez lire un .json
fichier mis à jour en continu. Vous pouvez utiliser un hack . Mais à ce stade, il est plus facile à utiliser simplement fs
..json
extension, require
ne traitera pas le contenu du fichier comme JSON.Sérieusement! UtilisezJSON.parse
.
load-json-file
moduleSi vous lisez un grand nombre de .json
fichiers (et si vous êtes extrêmement paresseux), il devient ennuyeux d'écrire du code passe-partout à chaque fois. Vous pouvez enregistrer certains caractères en utilisant le load-json-file
module.
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 le contenu JSON est diffusé sur le réseau, vous devez utiliser un analyseur JSON en continu. Sinon, il bloquera votre processeur et étouffera votre boucle d'événements jusqu'à ce que le contenu JSON soit entièrement diffusé.
Il existe de nombreux packages disponibles dans NPM pour cela. Choisissez ce qui vous convient le mieux.
Si vous ne savez pas si tout ce qui est transmis JSON.parse()
est du JSON valide , assurez-vous de placer l'appel à l' JSON.parse()
intérieur d'un try/catch
bloc. Une chaîne JSON fournie par l'utilisateur pourrait bloquer votre application et même entraîner des failles de sécurité. Assurez-vous que la gestion des erreurs est effectuée si vous analysez le JSON fourni en externe.
and could even lead to security holes
par curiosité, comment?
<script>...
, et que l'erreur est déversée du côté client, vous avez un bogue XSS juste là. Par conséquent, l'OMI est important de gérer les erreurs JSON là où vous les analysez.
require
JSON?" et n'a même pas pris la peine de documenter les effets secondaires. Cela signifiait également que require accepte les fichiers dans deux langues: JavaScript et JSON (non, ce ne sont pas les mêmes). Voilà pour SRP.
utilisez l' objet JSON :
JSON.parse(str);
Un autre exemple 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);
});
Je voudrais mentionner qu'il existe des alternatives à l'objet JSON global.
JSON.parse
et JSON.stringify
sont tous les deux synchrones, donc si vous voulez traiter de gros objets, vous voudrez peut-être vérifier certains des modules JSON asynchrones.
Jetez un œil: https://github.com/joyent/node/wiki/Modules#wiki-parsers-json
JSON.parse
l'ensemble de votre application va planter ou, en utilisant process.on('uncaughtException', function(err) { ... });
, il n'y aura finalement aucune chance d'envoyer une erreur "JSON mal formé" à l'utilisateur.
async
analyseur? Je ne l'ai pas trouvé.
Incluez la node-fs
bibliothèque.
var fs = require("fs");
var file = JSON.parse(fs.readFileSync("./PATH/data.json", "utf8"));
Pour plus d'informations sur la bibliothèque 'fs', reportez-vous à la documentation sur http://nodejs.org/api/fs.html
Puisque vous ne savez pas que votre chaîne est réellement valide, je la mettrais d'abord dans un catch catch. De plus, comme les blocs try catch ne sont pas optimisés par nœud, je mettrais le tout dans une autre fonction:
function tryParseJson(str) {
try {
return JSON.parse(str);
} catch (ex) {
return null;
}
}
OU en "style asynchrone"
function tryParseJson(str, callback) {
process.nextTick(function () {
try {
callback(null, JSON.parse(str));
} catch (ex) {
callback(ex)
}
})
}
Analyser un flux JSON? Utilisez 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
}))
Tout le monde ici a parlé de JSON.parse, alors j'ai pensé à dire autre chose. Il existe un excellent module Se connecter avec de nombreux middleware pour faciliter et améliorer le développement d'applications. L'un des middleware est bodyParser . Il analyse JSON, les formulaires html, etc. Il existe également un middleware spécifique pour l'analyse JSON uniquement noop .
Jetez un œil aux liens ci-dessus, cela pourrait vous être très utile.
JSON.parse("your string");
C'est tout.
comme d'autres réponses ici l'ont mentionné, vous voudrez probablement exiger un fichier json local que vous savez sûr et présent, comme un fichier de configuration:
var objectFromRequire = require('path/to/my/config.json');
ou pour utiliser l'objet JSON global pour analyser une valeur de chaîne dans un objet:
var stringContainingJson = '\"json that is obtained from somewhere\"';
var objectFromParse = JSON.parse(stringContainingJson);
notez que lorsque vous avez besoin d'un fichier, le contenu de ce fichier est évalué, ce qui introduit un risque de sécurité au cas où ce ne serait pas un fichier json mais un fichier js.
ici, j'ai publié une démo où vous pouvez voir les deux méthodes et jouer avec elles en ligne (l'exemple d'analyse est dans le fichier app.js - puis cliquez sur le bouton Exécuter et voyez le résultat dans le terminal): http: // staging1 .codefresh.io / labs / api / env / json-parse-example
vous pouvez modifier le code et voir l'impact ...
Vous utilisez JSON pour votre configuration avec Node.js? Lisez ceci et obtenez vos compétences de configuration sur 9000 ...
Remarque: personnes affirmant que data = require ('./ data.json'); est un risque pour la sécurité et la rétrogradation des réponses des gens avec un zèle zélé: vous avez exactement et complètement tort . Essayez de placer des fichiers non JSON dans ce fichier ... Node vous donnera une erreur, exactement comme si vous faisiez la même chose avec le fichier manuel beaucoup plus lent et plus difficile à coder, puis JSON.parse (). Veuillez cesser de diffuser de la désinformation; tu blesses le monde, tu n'aides pas. Le nœud a été conçu pour permettre cela; ce n'est pas un risque pour la sécurité!
Les applications appropriées sont disponibles dans plus de 3 couches de configuration:
La plupart des développeurs traitent leur configuration de serveur et d'application comme si elle pouvait changer. Ça ne peut pas. Vous pouvez superposer les modifications des couches supérieures les unes sur les autres, mais vous modifiez les exigences de base . Certaines choses doivent exister! Faites en sorte que votre configuration agisse comme immuable, car certaines d'entre elles le sont essentiellement, tout comme votre code source.
Ne pas voir que beaucoup de vos choses ne changeront pas après le démarrage conduit à des anti-modèles comme joncher votre chargement de configuration avec des blocs try / catch, et prétendre que vous pouvez continuer sans votre application correctement configurée. Tu ne peux pas. Si vous le pouvez, cela appartient à la couche de configuration communauté / utilisateur, pas à la couche de configuration serveur / application. Vous faites juste mal. Les éléments facultatifs doivent être superposés lorsque l'application termine son amorçage.
Arrêtez de vous cogner la tête contre le mur: votre configuration doit être ultra simple .
Jetez un œil à la facilité de configuration de quelque chose d'aussi complexe qu'un framework de service indépendant du protocole et indépendant de la source de données à l'aide d'un simple fichier de configuration json et d'un simple fichier 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 ... (le moteur qui fait tout fonctionner)
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 ... (le code qui alimente votre service indépendant du protocole et indépendant de la source de données)
module.exports = function(request, response){
response.end('Responding to: ' + request.url);
}
En utilisant ce modèle, vous pouvez maintenant charger des éléments de configuration de communauté et d'utilisateur au-dessus de votre application démarrée, dev ops est prêt à placer votre travail dans un conteneur et à le mettre à l'échelle. Vous êtes lu pour plusieurs locataires. Userland est isolé. Vous pouvez maintenant séparer les préoccupations du protocole de service que vous utilisez, du type de base de données que vous utilisez et vous concentrer uniquement sur l'écriture d'un bon code.
Parce que vous utilisez des couches, vous pouvez compter sur une seule source de vérité pour tout, à tout moment (l'objet de configuration en couches), et éviter les vérifications d'erreurs à chaque étape, en vous inquiétant de "oh merde, comment vais-je faire cela travailler sans configuration correcte?!? ".
Ma solution:
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
erreurs - une idée par où commencer à déboguer ce problème?
Je veux juste compléter la réponse (car j'ai eu du mal avec ça pendant un certain temps), je veux montrer comment accéder aux informations json, cet exemple montre comment accéder à 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);
}
})
Juste pour rendre cela aussi compliqué que possible, et apporter autant de paquets que possible ...
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);
Cela vous permet de faire:
var dataPromise = readJsonFile("foo.json");
dataPromise.then(console.log);
Ou si vous utilisez async / wait:
let data = await readJsonFile("foo.json");
L'avantage par rapport à la simple utilisation readFileSync
est que votre serveur Node peut traiter d'autres requêtes pendant la lecture du fichier sur le disque.
JSON.parse n'assurera pas la sécurité de la chaîne json que vous analysez. Vous devriez regarder une bibliothèque comme json-safe-parse ou une bibliothèque similaire.
À partir de la page npm de json-safe-parse:
JSON.parse est génial, mais il a un sérieux défaut dans le contexte de JavaScript: il vous permet de remplacer les propriétés héritées. Cela peut devenir un problème si vous analysez JSON à partir d'une source non fiable (par exemple: un utilisateur) et que vous appelez des fonctions que vous attendez.
Tirez parti de la fonction de tentative de Lodash pour renvoyer un objet d'erreur, que vous pouvez gérer avec la fonction 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
au lieu d'utiliser simplement _.attempt (JSON.parse, str)
Assurez-vous toujours d'utiliser JSON.parse dans le bloc try catch car le nœud renvoie toujours une erreur inattendue si vous avez des données corrompues dans votre json, utilisez donc ce code au lieu du simple JSON.Parse
try{
JSON.parse(data)
}
catch(e){
throw new Error("data is corrupted")
}
Si vous souhaitez ajouter des commentaires dans votre JSON et autoriser les virgules de fin, vous pouvez utiliser ci-dessous l'implémentation:
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);
}
Notez que cela pourrait ne pas bien fonctionner si vous avez quelque chose comme "abc": "foo // bar"
dans votre JSON. Alors YMMV.
Si le fichier source JSON est assez volumineux, vous pouvez envisager la route asynchrone via l'approche asynchrone / attente native avec Node.js 8.0 comme suit
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))
J'utilise fs-extra . Je l'aime beaucoup parce que, même s'il prend en charge les rappels, il prend également en charge les promesses . Cela me permet donc d'écrire mon code d'une manière beaucoup plus lisible:
const fs = require('fs-extra');
fs.readJson("path/to/foo.json").then(obj => {
//Do dome stuff with obj
})
.catch(err => {
console.error(err);
});
Il possède également de nombreuses méthodes utiles qui ne sont pas fournies avec le fs
module standard et , en plus de cela, il relie également les méthodes du fs
module natif et les promet.
REMARQUE: vous pouvez toujours utiliser les méthodes Node.js natives. Ils sont promis et copiés sur fs-extra. Voir les notes sur
fs.read()
&fs.write()
C'est donc essentiellement tous les avantages. J'espère que d'autres trouveront cela utile.
Si vous devez analyser JSON avec Node.js de manière sécurisée (alias: l'utilisateur peut entrer des données ou une API publique), je suggérerais d'utiliser secure-json-parse .
L'utilisation est similaire à celle par défaut, JSON.parse
mais elle protégera votre code contre:
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
Vous pouvez utiliser JSON.parse () (qui est une fonction intégrée qui vous forcera probablement à l'envelopper avec des instructions try-catch).
Ou utilisez une bibliothèque npm d'analyse JSON, quelque chose comme json-parse-or
Utilisez ceci pour être du bon côté
var data = JSON.parse(Buffer.concat(arr).toString());
NodeJs est un serveur basé sur JavaScript , vous pouvez donc faire comme vous le faites en JavaScript pur ...
Imaginez que vous avez ce Json dans NodeJs ...
var details = '{ "name": "Alireza Dezfoolian", "netWorth": "$0" }';
var obj = JSON.parse(details);
Et vous pouvez faire ci-dessus pour obtenir une version analysée de votre json ...
Comme mentionné dans les réponses ci-dessus, nous pouvons utiliser JSON.parse()
pour analyser les chaînes en JSON Mais avant d'analyser, assurez-vous d'analyser les données correctes, sinon cela pourrait faire baisser votre application entière
il est sûr de l'utiliser comme ça
let parsedObj = {}
try {
parsedObj = JSON.parse(data);
} catch(e) {
console.log("Cannot parse because data is not is proper json format")
}
Utilisez JSON.parse(str);
. En savoir plus ici .
Voici quelques exemples:
var jsonStr = '{"result":true, "count":42}';
obj = JSON.parse(jsonStr);
console.log(obj.count); // expected output: 42
console.log(obj.result); // expected output: true
C'est simple, vous pouvez convertir JSON en chaîne en utilisant JSON.stringify(json_obj)
et convertir la chaîne en JSON en utilisant JSON.parse("your json string")
.