サーチ…


前書き

JSON(JavaScript Object Notation)は軽量なデータ交換フォーマットです。人間が読み書きすることは容易であり、機械が解析し生成することも容易である。 JavaScriptでは、JSONはオブジェクトではなく文字列であることに気づくことが重要です。

json.orgの Webサイトには、さまざまなプログラミング言語での標準の実装へのリンクが含まれています。

構文

  • JSON.parse(input [、reviver])
  • JSON.stringify(value [、replacer [、space]])

パラメーター

パラメータ詳細
JSON.parse JSON文字列を解析する
input(string) JSON文字列を解析します。
reviver(function) 入力JSON文字列の変換を指定します。
JSON.stringify 直列化可能な値を直列化する
value(string) JSON仕様に従ってシリアル化される値。
replacer(functionまたはString[]またはNumber[]) 選択的に、 valueオブジェクトの特定のプロパティが含まれます。
space(StringまたはNumber場合はnumber提供され、その後、 spaceの空白の数は、読みやすさの挿入されます。 stringを指定すると、文字列(最初の10文字)が空白として使用されます。

備考

JSONユーティリティメソッドは、 ECMAScript 5.1§15.12で最初に標準化されました

形式はJSONデータ交換フォーマット (2013年3月のRFC 7158、2013年10月のECMA-404 、2014年3月のRFC 7159)で後で更新されたJSON のapplication / json Media Type (RFC 4627 July 2006)で正式に定義されました。

これらのメソッドをInternet Explorer 8などの古いブラウザで使用できるようにするには、Douglas Crockfordのjson2.jsを使用します。

シンプルなJSON文字列の解析

JSON.parse()メソッドは文字列をJSONとして解析し、JavaScriptプリミティブ、配列、またはオブジェクトを返します。

const array = JSON.parse('[1, 2, "c", "d", {"e": false}]');
console.log(array); // logs: [1, 2, "c", "d", {e: false}]

値をシリアライズする

JavaScriptの値は、 JSON.stringify関数を使用してJSON文字列に変換できます。

JSON.stringify(value[, replacer[, space]])
  1. value JSON文字列に変換する値。
/* Boolean */  JSON.stringify(true)             // 'true'
/* Number  */  JSON.stringify(12)               // '12'
/* String  */  JSON.stringify('foo')            // '"foo"'
/* Object  */  JSON.stringify({})               // '{}'
               JSON.stringify({foo: 'baz'})     // '{"foo": "baz"}'
/* Array   */  JSON.stringify([1, true, 'foo']) // '[1, true, "foo"]'
/* Date    */  JSON.stringify(new Date())       // '"2016-08-06T17:25:23.588Z"'
/* Symbol  */  JSON.stringify({x:Symbol()})     // '{}'
  1. replacer JSON文字列に含める値オブジェクトのプロパティをフィルタリングするためのホワイトリストとして機能する文字列処理プロセスまたはStringオブジェクトとNumberオブジェクトの配列を変更する関数です。この値がnullまたは指定されていない場合は、オブジェクトのすべてのプロパティがJSON文字列に含まれます。
// replacer as a function
function replacer (key, value) {
    // Filtering out properties
    if (typeof value === "string") {
        return
    }    
    return value
}

var foo = { foundation: "Mozilla", model: "box", week: 45, transport: "car", month: 7 }
JSON.stringify(foo, replacer)
// -> '{"week": 45, "month": 7}'
// replacer as an array
JSON.stringify(foo, ['foundation', 'week', 'month'])
// -> '{"foundation": "Mozilla", "week": 45, "month": 7}'
// only the `foundation`, `week`, and `month` properties are kept
  1. space読みやすくするために、インデントに使用するスペースの数を3番目のパラメーターとして指定することができます。
JSON.stringify({x: 1, y: 1}, null, 2)  // 2 space characters will be used for indentation
/* output:
    {
      'x': 1,
      'y': 1
    }
*/

あるいは、インデントに使用する文字列値を指定することもできます。たとえば'\t'を渡すと、タブ文字がインデントに使用されます。

JSON.stringify({x: 1, y: 1}, null, '\t')
/* output:
    {
        'x': 1,
        'y': 1
    }
*/

Replacer関数を使用したシリアライズ

replacer関数を使用して、直列化された値をフィルタリングまたは変換することができます。

const userRecords = [
  {name: "Joe", points: 14.9, level: 31.5},
  {name: "Jane", points: 35.5, level: 74.4},
  {name: "Jacob", points: 18.5, level: 41.2},
  {name: "Jessie", points: 15.1, level: 28.1},
];

// Remove names and round numbers to integers to anonymize records before sharing
const anonymousReport = JSON.stringify(userRecords, (key, value) =>
  key === 'name'
    ? undefined
    : (typeof value === 'number' ? Math.floor(value) : value)
);

これにより、次の文字列が生成されます。

'[{"points":14,"level":31},{"points":35,"level":74},{"points":18,"level":41},{"points":15,"level":28}]'

reviver関数を使った構文解析

reviver関数を使用して、解析される値をフィルタリングまたは変換することができます。

5.1
var jsonString = '[{"name":"John","score":51},{"name":"Jack","score":17}]';

var data = JSON.parse(jsonString, function reviver(key, value) {
  return key === 'name' ? value.toUpperCase() : value;
});
6
const jsonString = '[{"name":"John","score":51},{"name":"Jack","score":17}]';

const data = JSON.parse(jsonString, (key, value) =>
  key === 'name' ? value.toUpperCase() : value
);

これにより、次の結果が得られます。

[
  {
    'name': 'JOHN',
    'score': 51
  },
  {
    'name': 'JACK',
    'score': 17
  }
]

これは、JSONで送信する際にシリアル化/エンコードする必要があるデータを送信する必要がある場合に、デシリアライズ/デコードにアクセスする必要がある場合に特に便利です。次の例では、日付がISO 8601表現にエンコードされています。 reviver関数を使用してJavaScript Dateこれを解析します。

5.1
var jsonString = '{"date":"2016-01-04T23:00:00.000Z"}';

var data = JSON.parse(jsonString, function (key, value) {
  return (key === 'date') ? new Date(value) : value;
});
6
const jsonString = '{"date":"2016-01-04T23:00:00.000Z"}';

const data = JSON.parse(jsonString, (key, value) =>
  key === 'date' ? new Date(value) : value
);

reviver関数が各反復の最後に有用な値を返すことを確認することが重要です。 reviver関数がundefined返すか、値がないか、関数の最後に向かって実行が終了すると、プロパティはオブジェクトから削除されます。それ以外の場合、プロパティは戻り値として再定義されます。

クラスインスタンスの直列化と復元

カスタムのtoJSONメソッドとリバーブ関数を使用して、JSONで独自のクラスのインスタンスを送信できます。オブジェクトにtoJSONメソッドがある場合、その結果はオブジェクト自体ではなくシリアル化されます。

6
function Car(color, speed) {
  this.color = color;
  this.speed = speed;
}

Car.prototype.toJSON = function() {
  return {
    $type: 'com.example.Car',
    color: this.color,
    speed: this.speed
  };
};

Car.fromJSON = function(data) {
  return new Car(data.color, data.speed);
};
6
class Car {
  constructor(color, speed) {
    this.color = color;
    this.speed = speed;
    this.id_ = Math.random();
  }

  toJSON() {
    return {
      $type: 'com.example.Car',
      color: this.color,
      speed: this.speed
    };
  }

  static fromJSON(data) {
    return new Car(data.color, data.speed);
  }
}
var userJson = JSON.stringify({
  name: "John",
  car: new Car('red', 'fast')
});

これにより、次の内容の文字列が生成されます。

{"name":"John","car":{"$type":"com.example.Car","color":"red","speed":"fast"}}
var userObject = JSON.parse(userJson, function reviver(key, value) {
  return (value && value.$type === 'com.example.Car') ? Car.fromJSON(value) : value;
});

これにより、次のオブジェクトが生成されます。

{
  name: "John",
  car: Car {
    color: "red",
    speed: "fast",
    id_: 0.19349242527065402
  }
}

JSONとJavaScriptリテラルの比較

JSONは "JavaScript Object Notation"の略ですが、JavaScriptではありません。 JavaScriptのリテラルとして直接使用できるデータのシリアル化フォーマットと考えることできます。ただし、外部ソースからフェッチされたJSONを直接実行することは推奨されません( eval()を介してeval() 。機能的には、JSONはXMLやYAMLとあまり違いはありません.JSONがJavaScriptと非常によく似たシリアライズフォーマットとして想像されるなら、いくつかの混乱を避けることができます。

その名前は単なるオブジェクトを意味しますが、ある種のAPIによるユースケースの大半は常にオブジェクトや配列になりますが、JSONは単なるオブジェクトや配列ではありません。次のプリミティブ型がサポートされています。

  • 文字列(例: "Hello World!"
  • 番号(例えば42
  • ブール値(例: true
  • null

undefinedは、シリアル化時にJSONから未定義のプロパティが省略されるという意味ではサポートされていません。したがって、JSONを逆シリアル化し、その値がundefinedプロパティで終わる方法はありundefined

文字列"42"は有効なJSONです。 JSONは必ず"{...}"または"[...]"外部エンベロープを持つ必要はありません。

nome JSONも有効なJavaScriptであり、いくつかのJavaScriptも有効なJSONですが、両方の言語には微妙な違いがあり、どちらの言語も他の言語のサブセットではありません。

以下のJSON文字列を例に挙げてください:

{"color": "blue"}

これはJavaScriptに直接挿入できます。構文的に有効で、正しい値が得られます。

const skin = {"color": "blue"};

しかし、 "color"は有効な識別子名であり、プロパティ名の前後の引用符は省略できます。

const skin = {color: "blue"};

二重引用符の代わりに一重引用符を使用できることも知っています。

const skin = {'color': 'blue'};

しかし、これらのリテラルを両方ともJSONとして扱うとすると、 どちらも構文上有効な JSONではありません

{color: "blue"}
{'color': 'blue'}

JSONでは、すべてのプロパティ名を二重引用符で囲む必要があり、文字列値も二重引用符で囲む必要があります。

JSONの初心者にとっては、JavaScriptのリテラルをJSONとして使用してコードの抜粋を使用し、JSONパーサーから取得した構文エラーについては頭を悩ますのが一般的です。

コードや会話で誤った用語が適用されると、混乱が起こり始めます。

一般的なアンチパターンは、非JSON値を "json"とする変数に名前を付けることです。

fetch(url).then(function (response) {
  const json = JSON.parse(response.data); // Confusion ensues!

  // We're done with the notion of "JSON" at this point,
  // but the concept stuck with the variable name.
});

上の例では、 response.dataは、いくつかのAPIによって返されるJSON文字列です。 JSONはHTTP応答ドメインで停止します。 "json"という名前の変数にはJavaScriptの値だけが格納されています(オブジェクト、配列、または単純な数値であってもかまいません)。

上記を書くのにあまり混乱させない方法は次のとおりです。

fetch(url).then(function (response) {
  const value = JSON.parse(response.data);

  // We're done with the notion of "JSON" at this point.
  // You don't talk about JSON after parsing JSON.
});

開発者は、多くの周りに "JSONオブジェクト"というフレーズをスローする傾向があります。これは混乱の原因にもなります。上記のように、JSON文字列は値としてオブジェクトを保持する必要はありません。 「JSON文字列」はより良い用語です。 XML文字列やYAML文字列と似ています。あなたは文字列を取得し、それを解析して、値を返します。

周期オブジェクト値

すべてのオブジェクトをJSON文字列に変換できるわけではありません。オブジェクトに周期的な自己参照がある場合、変換は失敗します。

これは、通常、親データと子データが互いに参照する階層データ構造の場合です。

const world = {
  name: 'World',
  regions: []
};

world.regions.push({
  name: 'North America',
  parent: 'America'
});
console.log(JSON.stringify(world));
// {"name":"World","regions":[{"name":"North America","parent":"America"}]}

world.regions.push({
  name: 'Asia',
  parent: world
});

console.log(JSON.stringify(world));
// Uncaught TypeError: Converting circular structure to JSON

プロセスがサイクルを検出すると、例外が発生します。サイクル検出がない場合、文字列は無限に長くなります。



Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow