Как разобрать JSON с помощью Node.js?

934

Как мне разобрать JSON с помощью Node.js? Есть ли какой-нибудь модуль, который будет надежно проверять и разбирать JSON?

Теги:

32 ответа

1025
Лучший ответ

Вы можете просто использовать JSON.parse.

Определение объекта JSON является частью спецификации ECMAScript 5. node.js построен на движке Google Chrome V8, который соответствует стандарту ECMA. Следовательно, node.js также имеет глобальный объект JSON [docs].

Примечание. JSON.parse может связать текущий поток, потому что это синхронный метод. Поэтому, если вы планируете анализировать большие объекты JSON, используйте потоковый анализатор json.

  • 3
    Не думал об этом - я думаю, я не сделал достаточно JavaScript в браузере ...
  • 0
    Кто-нибудь знает, почему этого нет в официальной документации? Или, если он есть, где его найти?
Показать ещё 5 комментариев
602

вы можете require.json файлы.

var parsedJSON = require('./file-name');

Например, если у вас есть файл config.json в том же каталоге, что и файл исходного кода, который вы использовали бы:

var config = require('./config.json');

или (расширение файла может быть опущено):

var config = require('./config');

обратите внимание, что require является синхронным и только читает файл один раз, следующие вызовы возвращают результат из кеша

Также обратите внимание. Вы должны использовать это только для локальных файлов под вашим абсолютным контролем, так как он потенциально выполняет любой код внутри файла.

  • 4
    Если вы используете этот метод для анализа файла, обязательно примите во внимание путь для запроса. Например, вам может потребоваться сделать что-то вроде этого: require './file-name-with-no-extension' (например, если файл находится в текущем каталоге)
  • 0
    @SnapShot true, добавил конкретный пример.
Показать ещё 15 комментариев
297

Вы можете использовать JSON.parse().

Вы должны иметь возможность использовать объект JSON в любой реализации JavaScript, совместимой с ECMAScript 5. И V8, на котором построен Node.js, является одним из них.


Разбор строки, содержащей данные JSON

var str = '{ "name": "John Doe", "age": 42 }';
var obj = JSON.parse(str);

Разбор файла, содержащего данные JSON

Вам придется выполнить некоторые файловые операции с модулем fs.

Асинхронная версия

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? Подумай еще раз!

Иногда вы можете использовать require:

var obj = require('path/to/file.json');

Но я не рекомендую это по нескольким причинам:

Примечание. Если вы используете файл JSON для хранения конфиденциальной информации (например, паролей), это неправильный способ сделать это. Посмотрите, как Heroku делает это: https://devcenter.heroku.com/articles/config-vars#setting-up-config-vars-for-a-deployed-application. Узнайте, как ваша платформа это делает, и используйте process.env для получения конфигурационных переменных из кода.

  1. require синхронно. Если у вас очень большой JSON файл, он захлебнется в вашем цикле событий. Вам действительно нужно использовать JSON.parse с fs.readFile.
  2. require будет прочитать файл только один раз. Последующие вызовы, require для того же файла, вернут кэшированную копию. Не очень хорошая идея, если вы хотите прочитать файл .json который постоянно обновляется. Вы могли бы использовать взломать. Но с этого момента проще просто использовать fs.
  3. Если ваш файл не имеет расширения .json, require не будет обрабатывать содержимое файла как JSON.

Шутки в сторону! Используйте JSON.parse.


модуль load-json-file

Если вы читаете большое количество файлов .json (и если вы очень ленивы), каждый раз становится неудобно писать шаблонный код. Вы можете сохранить некоторые символы с помощью модуля load-json-file.

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');

Разбор JSON из потоков

Если содержимое JSON передается по сети, вам необходимо использовать потоковый анализатор JSON. В противном случае он свяжет ваш процессор и закроет цикл обработки событий, пока содержимое JSON не будет полностью передано.

Для этого в NPM доступно множество пакетов. Выберите то, что лучше для вас.


Обработка ошибок/Безопасность

Если вы не уверены, что все, что передается в JSON.parse() является допустимым JSON, обязательно JSON.parse() вызов JSON.parse() в блок try/catch. Предоставленная пользователем строка JSON может привести к сбою приложения и даже к дырам в безопасности. Убедитесь, что обработка ошибок выполнена, если вы анализируете предоставленный извне JSON.

  • 2
    and could even lead to security holes из любопытства, как?
  • 6
    @natario: мы говорим о серверной части JS здесь. Предположим, кто-то анализирует пользовательский JSON. Если предполагается, что JSON всегда правильно сформирован, злоумышленник может отправить какой-то искаженный JSON, чтобы вызвать ошибку, которая, если она передана клиентской стороне, может раскрыть важную информацию о системе. Или, если JSON был неверно сформирован и содержал некоторый текст с <script>... , и ошибка была передана на клиентскую сторону, у вас есть ошибка XSS. Поэтому IMO важно обрабатывать ошибки JSON там, где вы их анализируете.
Показать ещё 10 комментариев
82

используйте объект JSON:

JSON.parse(str);
  • 10
    Это просто дублирует верхний ответ. Пожалуйста, рассмотрите возможность его удаления; вы будете держать очки.
  • 0
    @DanDascalescu - Этому ответу 3 года, кого это волнует?
Показать ещё 7 комментариев
34

Другой пример 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);
});
  • 2
    Мне нравится, что этот подход не требует, чтобы файл json был локальным для приложения. Спасибо!
33

Я хотел бы упомянуть, что есть альтернативы глобальному объекту JSON. JSON.parse и JSON.stringify являются синхронными, поэтому, если вы хотите иметь дело с большими объектами, вы можете проверить некоторые из асинхронных модулей JSON.

Посмотрите: https://github.com/joyent/node/wiki/Modules#wiki-parsers-json

  • 1
    Это особенно верно, если вы ожидаете данные JSON от входящих соединений. Если неправильно сформированный JSON анализируется с помощью JSON.parse ваше приложение будет аварийно JSON.parse или, используя process.on('uncaughtException', function(err) { ... }); , в конечном счете, не будет возможности отправить пользователю "неправильную форму JSON".
  • 3
    Какой из них async парсер? Я не нашел это.
Показать ещё 2 комментария
29

Включите библиотеку node-fs.

var fs = require("fs");
var file = JSON.parse(fs.readFileSync("./PATH/data.json", "utf8"));

Для получения дополнительной информации о библиотеке fs см. документацию по адресу http://nodejs.org/api/fs.html

  • 2
    Возможно, стоит отметить, что вы должны заключить строку var файла в try / catch на тот случай, если ваш JSON не удастся разобрать или файл не существует.
  • 3
    Или просто воспользуйтесь обратным вызовом!
9

Поскольку вы не знаете, что ваша строка действительно действительна, я бы поставил ее сначала в try catch. Кроме того, поскольку блоки try catch не оптимизированы с помощью node, я бы поставил все это в другую функцию:

function tryParseJson(str) {
    try {
        return JSON.parse(str);
    } catch (ex) {
        return null;
    }
}

ИЛИ в "асинхронном стиле"

function tryParseJson(str, callback) {
    process.nextTick(function () {
      try {
          callback(null, JSON.parse(str));
      } catch (ex) {
          callback(ex)
      }
    })
}
  • 2
    Я просто хочу отметить, что process.nextTick не является aysnc. Это просто откладывает чтение файла до следующего вызова функции в цикле событий JS. Для асинхронного запуска JSON.parse вы используете поток, отличный от основного потока Node.js
8

Разбор потока JSON? Используйте 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
    }))

https://github.com/dominictarr/JSONStream

7
JSON.parse("your string");

Что все.

6

как уже упоминалось в других ответах, вы, вероятно, захотите либо потребовать, чтобы локальный json файл, который, как вы знаете, безопасен и присутствует, например файл конфигурации:

var objectFromRequire = require('path/to/my/config.json'); 

или использовать глобальный объект JSON для синтаксического анализа строкового значения в объекте:

var stringContainingJson = '\"json that is obtained from somewhere\"';
var objectFromParse = JSON.parse(stringContainingJson);

обратите внимание, что когда вам требуется файл, содержимое этого файла оценивается, что представляет угрозу безопасности, если это не файл json, а файл js.

здесь, я опубликовал демо, где вы можете увидеть оба метода и играть с ними в Интернете (пример синтаксического анализа находится в файле app.js - затем нажмите кнопку запуска и посмотрите результат в терминале): http://staging1.codefresh.io/labs/api/env/json-parse-example

вы можете изменить код и увидеть влияние...

  • 0
    Upvote для использования require ()
5

Мое решение:

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);
});
  • 0
    Спасибо @eloyesp, я пытался использовать этот код, но я продолжаю получать TypeError: path must be a string or Buffer ошибки TypeError: path must be a string or Buffer - есть идеи, где начать отладку этой проблемы?
5

Все здесь говорили о JSON.parse, поэтому я подумал сказать что-то еще. Существует большой модуль Connect с множеством промежуточных программ, чтобы упростить и улучшить разработку приложений. Одним из промежуточных программ является bodyParser. Он анализирует JSON, html-формы и т.д. Существует также специальное промежуточное программное обеспечение для анализа JSON только noop.

Взгляните на приведенные выше ссылки, это может быть очень полезно для вас.

4

Использование JSON для вашей конфигурации с помощью Node.js? Прочтите это и получите навыки настройки более 9000...

Примечание. Люди, утверждающие, что data = require ('./data.json'); это угроза безопасности и опрокидывание людей с усердным рвением: вы точно и полностью неправильно. Попробуйте помещать не-JSON в этот файл... Node даст вам ошибку, точно так же, как если бы вы сделали то же самое с гораздо более медленным и сложным для чтения ручного файла кода, а затем последующим JSON.parse(). Пожалуйста, прекратите распространять дезинформацию; вы причиняете боль миру, а не помогаете. Node был разработан, чтобы это разрешалось; это не угроза безопасности!

Надлежащие приложения входят в 3+ слои конфигурации:

  • Конфигурация сервера/контейнера
  • Конфигурация приложения
  • (необязательно) Конфиденциальность/Сообщество/Конфигурация организации
  • Конфигурация пользователя

Большинство разработчиков обрабатывают свой сервер и конфигурацию приложения, как будто он может меняться. Это невозможно. Вы можете изменять слои с более высоких слоев друг на друга, но вы изменяете базовые требования. Некоторые вещи должны существовать! Сделайте свою конфигурацию так, как будто она неизменна, потому что некоторые из них в основном такие же, как и исходный код.

Невозможно увидеть, что многие ваши вещи не будут меняться после запуска, приводит к тому, что анти-шаблоны, например, засоряют вашу конфигурационную загрузку с помощью блоков try/catch и притворяются, что вы можете продолжать без правильно приложения настройки. Вы не можете. Если это возможно, это относится к слою конфигурации сообщества/пользователя, а не к слою конфигурации сервера/приложения. Ты просто делаешь это неправильно. Необязательный материал должен быть наложен сверху, когда приложение завершит загрузку.

Прекратите стучать головой о стену: ваша конфигурация должна быть ультра простой.

Взгляните на то, как легко настроить что-то сложное, как инфраструктуру сервиса agnostic и datasource-agnostic, используя простой конфигурационный файл json и простой файл app.js...

контейнер-config.js...

{
    "service": {
        "type"  : "http",
        "name"  : "login",
        "port"  : 8085
    },
    "data": {
        "type"  : "mysql",
        "host"  : "localhost",
        "user"  : "notRoot",
        "pass"  : "oober1337",
        "name"  : "connect"
    }
}

index.js... (движок, который активирует все)

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... (код, который активирует агностическую службу протокола-агностик и источник данных)

module.exports = function(request, response){
    response.end('Responding to: ' + request.url);
}

Используя этот шаблон, вы можете теперь загружать файлы конфигурации сообщества и пользователя поверх загруженного приложения, dev ops готов засунуть вашу работу в контейнер и масштабировать его. Вы читаете для мутантов. Userland изолирована. Теперь вы можете разделить проблемы с тем протоколом обслуживания, который вы используете, какой тип базы данных вы используете, и просто сосредоточиться на написании хорошего кода.

Поскольку вы используете слои, вы можете полагаться на единственный источник истины для всего, в любое время (многоуровневый объект конфигурации), и избегать ошибок на каждом шагу, беспокоясь о "ох, как я иду" чтобы сделать эту работу без правильной конфигурации?!? ".

4

Просто хочу завершить ответ (поскольку я некоторое время боролся с ним), хочу показать, как получить доступ к json-информации, этот пример показывает доступ к 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);
  }
})
4

Просто сделайте это как можно более сложным и принесите как можно больше пакетов...

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);

Это позволяет:

var dataPromise = readJsonFile("foo.json");
dataPromise.then(console.log);

Или, если вы используете async/wait:

let data = await readJsonFile("foo.json");

Преимущество только при использовании readFileSync заключается в том, что ваш сервер Node может обрабатывать другие запросы, пока файл считывается с диска.

3

Если вы хотите добавить комментарии в свой JSON и разрешить запятые, вы можете использовать ниже реализации:

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);
}

Обратите внимание, что это может не сработать, если в вашем JSON есть что-то вроде "abc": "foo // bar". Итак, YMMV.

2

Обязательно используйте JSON.parse в блоке try catch, поскольку node всегда бросает непредвиденную ошибку, если у вас есть некорректные данные в вашем json, поэтому используйте этот код вместо простого JSON.Parse

try{
     JSON.parse(data)
}
catch(e){
   throw new Error("data is corrupted")
  }
2

Использовать функцию попытки Lodash для возврата объекта ошибки, с которым вы можете справиться с функцией 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
  • 3
    Можете ли вы объяснить, почему вы добавили .bind вместо того, чтобы просто использовать _.attempt (JSON.parse, str)
2

JSON.parse не гарантирует безопасность json-строки, которую вы разбираете. Вы должны посмотреть на библиотеку, например json-safe-parse или аналогичную библиотеку.

На странице json-safe-parse npm:

JSON.parse замечательный, но он имеет один серьезный недостаток в контексте JavaScript: он позволяет переопределять унаследованные свойства. Это может стать проблемой, если вы разбираете JSON из ненадежного источника (например, пользователя) и вызываете на нем функции, которые вы ожидаете существовать.

1

Я использую фс-экстра. Мне это очень нравится, потому что -although он поддерживает callbacks-, он также поддерживает Promises. Так что это просто позволяет мне писать свой код гораздо более читабельным способом:

const fs = require('fs-extra');
fs.readJson("path/to/foo.json").then(obj => {
    //Do dome stuff with obj
})
.catch(err => {
    console.error(err);
});

У него также есть много полезных методов, которые не входят в стандартный модуль fs и, кроме того, он также связывает методы из собственного модуля fs и обещает их.

ПРИМЕЧАНИЕ. Вы по-прежнему можете использовать собственные методы Node.js. Они обещаны и скопированы в fs-extra. Смотрите примечания к fs.read() и fs.write()

Так что в принципе все преимущества. Я надеюсь, что другие найдут это полезным.

1

Если исходный файл JSON довольно большой, возможно, стоит рассмотреть асинхронный маршрут с помощью нативного подхода async/await с Node.js 8.0 следующим образом

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))
1
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.');
0

NodeJs - это сервер на основе JavaScript, так что вы можете делать то же самое, что и в чистом JavaScript...

Представьте, что у вас есть этот Json в NodeJs...

var details = '{ "name": "Alireza Dezfoolian", "netWorth": "$0" }';
var obj = JSON.parse(details);

И вы можете сделать выше, чтобы получить разобранную версию вашего JSON...

0

Никаких дополнительных модулей не требуется.
Просто используйте
var parsedObj = JSON.parse(yourObj);
Я не думаю, что есть какие-либо проблемы безопасности в связи с этим

0

Используйте JSON.parse(str); , Подробнее читайте здесь.

Вот некоторые примеры:

var jsonStr = '{"result":true, "count":42}';

obj = JSON.parse(jsonStr);

console.log(obj.count);    //expected output: 42
console.log(obj.result);   // expected output: true
0

Используйте это, чтобы быть на безопасной стороне

var data = JSON.parse(Buffer.concat(arr).toString());
0

Вы можете использовать JSON.parse() (это встроенная функция, которая, вероятно, заставит вас заключить ее в операторы try-catch).

Или используйте некоторую JSON-библиотеку JSON для анализа, что-то вроде json-parse-or

0

Это нужно было кричать на меня: он работает только для файлов .json.

Если заканчивается файл, это не работает!

  • 1
    Кричать? Ни у кого нет времени на это!
-1

JSON.parse. Это самый простой способ для анализа JSON с помощью Node.js.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse

-2
var fs = require('fs');

fs.readFile('ashish.json',{encoding:'utf8'},function(data,err) {

   if(err) 
      throw err;

   else {

   console.log(data.toString());

 }
})
  • 0
    Хотя это может быть ответом, пожалуйста, предоставьте некоторый контекст и объяснение. Ответы только по коду не очень полезны для будущих посетителей .. и могут быть удалены.
-2

Это просто, вы можете преобразовать JSON в строку с помощью JSON.stringify(json_obj) и преобразовать строку в JSON с помощью JSON.parse("your json string").

  • 2
    Вы смотрели верхний ответ на этот вопрос? Ему 3 года и он очень полный. Что вы надеялись внести с помощью тривиальной информации, которую вы предлагаете здесь?
  • 2
    Теперь давайте не будем придерживаться двойного стандарта

Ещё вопросы

Сообщество Overcoder
Наверх
Меню