Node.jsを使用してJSONを解析する方法は?


回答:


1100

単純に使用できますJSON.parse

JSONオブジェクトの定義はECMAScript 5仕様の一部です。node.jsは、ECMA標準に準拠するGoogle ChromeのV8エンジンに基づいて構築されています。したがって、node.jsにもグローバルオブジェクト[ドキュメント]があります。JSON

注- JSON.parse同期メソッドであるため、現在のスレッドを拘束する可能性があります。したがって、大きなJSONオブジェクトの解析を計画している場合は、ストリーミングjsonパーサーを使用してください。


それが公式のドキュメントにない理由を誰かが知っていますか?または、ある場合、それをどこで見つけるか?
snapfractalpop 2012年

34
@snapfractalpop:ドキュメントでは、node.jsの一部である関数などについてのみ説明しています。標準のJavaScript機能はV8の一部であり、node.jsが組み込まれています。私はそれに応じて答えを更新しました。
Felix Kling

1
それの価値は、原料の束は、ノードのgithubのウィキにここにあります何のため@FelixKling:github.com/joyent/node/wiki/...
damianb

ここで、私はこの回答をオンラインで確認および再生できるデモを公開しました(解析例はapp.jsファイルにあります-次に、実行ボタンをクリックしてターミナルで結果を確認します):リンク コードを変更できます影響を確認してください...
nathan g

答えには、JavaScript構文の事前知識が必要です。使用例を示すのはどれほど難しいでしょうか?JSON.parse(str); //初心者にやさしいため、より適切な回答
webb

661

.jsonファイルを要求できます。

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

たとえばconfig.json、ソースコードファイルと同じディレクトリにファイルがある場合は、次のようにします。

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

または(ファイル拡張子は省略できます):

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

これrequire同期的で、ファイルを1回だけ読み取ることに注意してください。その後の呼び出しは、キャッシュから結果を返します。

また、これはファイル内のコードを実行する可能性があるため、絶対制御下のローカルファイルにのみ使用してください。


4
このメソッドを使用してファイルを解析している場合は、パスを必要に応じて考慮してください。たとえば、次のようにする必要がある場合があります。require './file-name-with-no-extension'(たとえば、ファイルが現在のディレクトリにある場合)
SnapShot

94
応答はキャッシュされることに注意してください。たとえば、上記のようにrequireを関数で呼び出し、関数を呼び出し、JSONファイルを変更して、もう一度関数を呼び出すと、古いバージョンのJSONファイルが取得されます。何度か私を捕まえた!
Ben Clayton

15
また、require同期していることに注意してください。fs.readFile代わりに非同期で使いたい場合JSON.parse
Evan Moran

29
このアプローチでは、ファイルをJavaScriptとして扱い、.jsonファイルで任意のコードを実行する可能性がありますか?
d11wtq 14

15
簡単なメモ:.json拡張機能を使用することを忘れないでください!ファイルに拡張子がない場合.json、requireはそれをjsonファイルとして扱いません。
Jason

323

使用できますJSON.parse()

ECMAScript 5互換のJavaScript実装でJSONオブジェクトを使用できるはずです。そして、Node.jsが構築されているV8もその1つです。

注:JSONファイルを使用して機密情報(パスワードなど)を格納している場合、それは間違った方法です。Herokuの仕組みをご覧くださいhttps : //devcenter.heroku.com/articles/config-vars#setting-up-config-vars-for-a-deployed-application。プラットフォームがそれをどのように行うかを調べ、を使用process.envしてコード内から構成変数を取得します。


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

しかし、これはいくつかの理由でお勧めしません。

  1. require同期です。非常に大きなJSONファイルがある場合、イベントループが詰まります。あなたは本当にで使用JSON.parseする必要がありますfs.readFile
  2. requireファイルは1回だけ読み込まれます。require同じファイルを次に呼び出すと、キャッシュされたコピーが返されます。.json継続的に更新されるファイルを読みたい場合はお勧めできません。あなたはハックを使うことができます。ただし、現時点では、を使用する方が簡単fsです。
  3. あなたのファイルが持っていない場合は.json拡張子を、requireJSONなどのファイルの内容を処理しません。

マジ!を使用し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()内で囲んでtry/catchください。ユーザーが提供したJSON文字列はアプリケーションをクラッシュさせる可能性があり、セキュリティホールにつながる可能性さえあります。外部から提供されたJSONを解析する場合は、エラー処理が行われていることを確認してください。


2
and could even lead to security holes好奇心から、どうやって?
natario 2016年

6
@natario:ここではサーバー側のJSについて話しています。誰かがユーザー提供のJSONを解析しているとします。JSONが常に正しい形式であると想定されている場合、攻撃者は不正な形式のJSONを送信してエラーをトリガーできます。クライアント側に流出した場合、システムに関する重要な情報が明らかになる可能性があります。または、JSONの形式が正しくなく、テキストが<script>...に含まれていて、エラーがクライアント側に流出した場合、XSSバグがそこにあります。したがって、IMOでは、解析する場所でJSONエラーを処理することが重要です。
sampathsris 2016年

1
@NickSteele:ただし、「これはおすすめできません」を「おすすめしない」に変更しました。私はあなたが今幸せであることを望みます。
sampathsris 2017年

1
@NickSteele:私が挙げた欠陥を考えると、うまく設計された機能だとは思わない。一部の人々が「requireJSONを含めるために使用するのはかっこいいと思いませんか?」副作用を文書化することさえしませんでした。これは、requireがJavaScriptとJSONの2つの言語でファイルを受け入れることも意味しました(同じではありません)。SRPはこれで終わりです。
sampathsris 2017年

1
@NickSteele:はい、設定に対してのみ正常に機能します。ただし、JSONは設定にのみ使用されるわけではありません。
sampathsris 2017年

85

JSONオブジェクトを使用します

JSON.parse(str);

12
これは、トップの回答を複製するだけです。削除をご検討ください。ポイントを維持します。
Dan Dascalescu 2014年

6
この回答には50の賛成票があります。1%のルールによると、おそらく5000人のユーザーがこの回答を読むのに時間を費やしているため、上位の回答には何も追加されません。それが3歳であることは問題を悪化させるだけです:)
Dan Dascalescu 14年

16
@DanDascalescu-気づくと思いますが、2つの回答は3年前にまったく同じ時刻に投稿されました。どちらも同じ情報を提供します。これはSO全体に当てはまります。受け入れられた回答ではなかったからといって、私の回答の半分を選別するつもりはありません。
Mark Kahn、

8
私はこの一連のコメントをかなり興味深いと感じましたが、答え自体は私の時間の浪費でした。...それが答えを削除する必要があることを意味するかどうかはわかりません。その場合、コメントスレッドは表示されなかったからです。しかし、そうでなければ私はそう言うでしょう。
MalcolmOcean 2015

7
@DanDascalescu、私はこの答えはより明確で要点があると思います。受け入れられたものは使用例を示しておらず、多くのリンクと余分なもののために混乱しています。
andresgottlieb 2015年

37

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ファイルがアプリケーションに対してローカルである必要がないことを気に入っています。ありがとうございました!
Charles Brandt

35

グローバルJSONオブジェクトの代替手段があることを述べておきます。 JSON.parseJSON.stringify同期の両方であるため、大きなオブジェクトを処理する場合は、いくつかの非同期JSONモジュールをチェックアウトすることをお勧めします。

見てください:https : //github.com/joyent/node/wiki/Modules#wiki-parsers-json


1
これは、着信接続からのJSONデータを予期している場合に特に当てはまります。不正な形式のJSONがJSON.parseアプリケーション全体で解析されている場合、クラッシュするか、を使用するとprocess.on('uncaughtException', function(err) { ... });、最終的にユーザーに「不正な形式のJSON」エラーを送信する機会がなくなります。
ポール、

3
どちらがasyncパーサーですか?見つかりませんでした。
bxshi 2013

3
リンクされたページは「廃止予定」とマークされ、「色あせた遺物」として自身を説明します。
誰もいない

30

node-fsライブラリを含めます。

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

「fs」ライブラリの詳細については、http://nodejs.org/api/fs.htmlにあるドキュメントを参照してください。


2
JSONが解析に失敗したり、ファイルが存在しない場合に備えて、varファイルの行をtry / catchでラップする必要があることに注意してください。
Fostah 2014

3
または、コールバックを使用してください!
lawx 2014

10

文字列が実際に有効であることを知らないので、私はまずそれをtry catchに入れます。また、try catchブロックはノードによって最適化されていないため、すべてを別の関数に入れます。

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スレッドとは異なるスレッドを使用する必要があります
Alexander Mills

9

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について語ったので、私は何か別のことを言うことを考えました。多くのミドルウェアと接続してアプリの開発をより簡単に、より良くするための素晴らしいモジュールがあります。ミドルウェアの1つはbodyParserです。JSON、htmlフォームなどを解析します。JSONがnoopのみを解析するための特定のミドルウェアもあります。

上記のリンクをご覧ください。非常に役立つ場合があります。



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

コードを変更して影響を確認できます...


5

Node.jsの構成にJSONを使用していますか?これを読んで、9000以上の構成スキルを身につけてください...

注:データを要求する人々= require( './ data.json'); はセキュリティリスクであり、熱心な熱意で人々の回答に反対票を投じます。あなたは正確かつ完全に間違っています。そのファイルに非JSONを配置してみてください... Nodeは、手動ファイルの読み取りをコーディングし、その後に続くJSON.parse()をコーディングするのがはるかに遅くて難しいコードで同じことをした場合とまったく同じように、エラーを出します。誤報の拡散をやめてください。あなたは世界を傷つけているのであって、助けていないのです。ノードはこれを可能にするように設計されました。セキュリティリスクではありません!

適切なアプリケーションには、3 層以上の構成があります。

  1. サーバー/コンテナ構成
  2. アプリケーション構成
  3. (オプション)テナント/コミュニティ/組織の構成
  4. ユーザー設定

ほとんどの開発者は、サーバーとアプリの構成を変更できるかのように扱います。できません。あなたはできる変化層互いの上に上位層からの、しかし、あなたはしている基本要件を変更します。いくつか存在する必要があります!ソースコードと同じように、構成の一部は基本的に不変であるため、構成を不変に動作させます。

起動後に構成の多くが変更されないことを確認しないと、try / catchブロックで構成の読み込みを散らかし、アプリケーションを適切にセットアップしなくても続行できるふりをするなど、アンチパターンが発生します。できません。可能であれば、それはサーバー/アプリ構成層ではなく、コミュニティ/ユーザー構成層に属します。あなたはただそれを間違っているのです。オプションのものは、アプリケーションがブートストラップを終了したときに上に重ねる必要があります。

頭を壁にぶつけないでください。設定は非常にシンプルでなければなりません。

単純なjson構成ファイルと単純な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 ...(すべてを動かすエンジン)

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

このパターンを使用して、起動したアプリの上にコミュニティとユーザーの設定をロードできるようになりました。開発者は作業をコンテナに入れてスケーリングする準備ができています。あなたはマルチテナントについて読まれています。ユーザーランドは孤立しています。これで、使用しているサービスプロトコル、使用しているデータベースタイプの問題を分離し、適切なコードの作成に集中できます。

あなたがレイヤーを使用しているので、あなたはああがらくた、どのように私はするつもりです」心配を、任意の時間(層状のconfigオブジェクト)で、すべての真理の単一のソースに依存し、すべてのステップで回避エラーチェックすることができ、これを適切な設定なしで動作しますか?!?」


4

私の解決策:

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

@eloyespに感謝します。このコードを使用してみましたが、TypeError: path must be a string or Bufferエラーが発生し続けます-この問題のデバッグをどこから始めればよいですか?
GPP

4

答えを完成させたい(しばらくの間私はそれで苦労した)、json情報へのアクセス方法を示したい、この例はJson配列へのアクセスを示しています。

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


3

これをできるだけ複雑にし、できるだけ多くのパッケージを取り込むために...

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 / awaitを使用している場合:

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

使用するだけの利点readFileSyncは、ファイルがディスクから読み取られている間にノードサーバーが他のリクエストを処理できることです。


2

JSON.parseは、解析しているjson文字列の安全性を保証しません。あなたのようなライブラリをご覧くださいJSON-安全解析または類似のライブラリ。

json-safe-parse npmページから:

JSON.parseはすばらしいですが、JavaScriptのコンテキストに重大な欠陥が1つあります。継承されたプロパティを上書きできるためです。信頼できないソース(例:ユーザー)からJSONを解析し、その上で存在すると予想される関数を呼び出す場合、これは問題になる可能性があります。


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)を使用する代わりに追加した理由を説明できますか
steviejay

2

jsonに破損したデータがある場合、ノードは常に予期しないエラーをスローするためtry catchブロックで常にJSON.parseを使用してください。単純なJSON.Parseの代わりにこのコードを使用してください。

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

1

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

"abc": "foo // bar"JSONの中に何かがある場合、うまく機能しない可能性があることに注意してください。だからYMMV。


1

JSONソースファイルがかなり大きい場合、Node.js 8.0でのネイティブのasync / awaitアプローチによる非同期ルートを次のように検討する必要があるかもしれません

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

私はfs-extraを使用しています。それはcallbacks-をサポート-althoughそれもサポートしているので、それのように、私はたくさんの約束を。したがって、コードをはるかに読みやすい方法で記述できるようになります。

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

安全な方法でNode.jsを使用してJSONを解析する必要がある場合(別名:ユーザーがデータを入力できる、またはパブリックAPI)、secure-json-parseを使用することをお勧めします

使用法はデフォルトのようですJSON.parseが、コードは次のことから保護されます。

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

0

JSON.parse()を使用できます(これは、try-catchステートメントでラップするように強制する組み込み関数です)。

または、json-parse-orのようなJSON解析npmライブラリを使用してください



0

NodeJsJavaScriptベースのサーバーなので、純粋なJavaScriptで行う方法と同じようにできます ...

あなたは、この持っている想像JSONNodeJs ...

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

そして、あなたはあなたのjsonの解析されたバージョンを取得するために上記を行うことができます...


0

上記の回答で述べたように、 JSON.parse()、文字列をJSONに解析、解析する前に、必ず正しいデータを解析してください。そうしないと、アプリケーション全体がダウンする可能性があります

このように使用しても安全です

let parsedObj = {}
try {
    parsedObj = JSON.parse(data);
} catch(e) {
    console.log("Cannot parse because data is not is proper json format")
}


-1

これ以上のモジュールは必要ありません。
ただ、使用
var parsedObj = JSON.parse(yourObj);
私ドンはこれについてどのようなセキュリティ上の問題があると思い


-2

シンプルですJSON.stringify(json_obj)。JSONをを使用して文字列に変換し、を使用して文字列をJSONに変換できますJSON.parse("your json string")


2
この質問のトップアンサーを見ましたか?それは3歳で非常に完全です。ここで提供している簡単な情報で何を貢献したいと思っていましたか?
Robby Cornelissen 2014年

2
さて、今、二重の基準を保持しましょう
ダニエルハノーバー2014
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.