#JSON オブジェクト

JSON形式

JSON 形式 (JavaScript Object Notation の略) は、煩雑な XML 形式を置き換えるために 2001 年に Douglas Crockford によって提案されたデータ交換用のテキスト形式です。

XML 形式と比較して、JSON 形式には 2 つの大きな利点があります。1 つは、記述が簡単で一目でわかること、ネイティブ JavaScript 構文に準拠しており、追加の解析コードを追加せずに解釈エンジンによって直接処理できることです。したがって、JSON はすぐに受け入れられ、主要な Web サイトがデータを交換するための標準形式となり、標準に組み込まれました。

各 JSON オブジェクトは値であり、配列、オブジェクト、またはプリミティブ型の値の場合があります。つまり、2 つ以上の値ではなく、1 つの値のみを指定できます。

JSON には、値の型と形式に関して厳格な規制があります。

  1. 複合型の値は、関数、正規表現オブジェクト、または日付オブジェクトではなく、配列またはオブジェクトのみにすることができます。

  2. プリミティブ型の値は 4 種類のみです: 文字列、数値 (10 進数で表現する必要があります)、ブール値、および null (NaNInfinity-Infinity、および unknown は使用できません)使用済み)。

  3. 文字列は二重引用符で表す必要があり、一重引用符は使用できません。

  4. オブジェクトのキー名は二重引用符で囲む必要があります。

  5. 配列またはオブジェクトの最後のメンバーの後にカンマを置くことはできません。

以下はすべて有効な JSON です。

["1 2 3"]

{ "1": 1"2": 2"3": 3 }

{"名前": ["張三""李思"] }

[ { "name": "張三"}, {"name": "李思"} ]

以下はすべて不正な JSON です。

{ name: "Zhang San", 'age': 32 } // 属性名には二重引用符を使用する必要があります

[32, 64, 128, 0xFFF] // 16進数値は使用できません

{ "name": "Zhang San", "age": 未定義 } // 未定義は使用できません

{ "名前": "張三",
  "誕生日": 新しい日付('金曜日、2011 年 8 月 26 日 07:13:10 GMT')、
  "getName": function () {
      this.name を返します。
  }
} // 属性値には関数と日付オブジェクトを使用できません

「null」、空の配列、および空のオブジェクトはすべて正当な JSON 値であることに注意してください。

JSON オブジェクト

JSON オブジェクトは JavaScript のネイティブ オブジェクトであり、JSON 形式のデータを処理するために使用されます。これには、「JSON.stringify()」と「JSON.parse()」という 2 つの静的メソッドがあります。

JSON.stringify()

基本的な使い方

JSON.stringify() メソッドは、値を JSON 文字列に変換するために使用されます。文字列は JSON 形式に準拠しており、JSON.parse() メソッドで解析できます。

JSON.stringify('abc') // ""abc""
JSON.stringify(1) // "1"
JSON.stringify(false) // "false"
JSON.stringify([]) // "[]"
JSON.stringify({}) // "{}"

JSON.stringify([1, "false", false])
// '[1,"false",false]'

JSON.stringify({ 名前: "張三" })
// '{"名前":"張三"}'

上記のコードは、さまざまな種類の値を JSON 文字列に変換します。

プリミティブ型文字列の場合、変換結果は二重引用符で囲まれることに注意してください。

JSON.stringify('foo') === "foo" // false
JSON.stringify('foo') === "\"foo\"" // true

上記のコードでは、文字列 foo"\"foo\"" に変換されます。これは、将来復元するときに、内側の二重引用符によって、これが文字列であり、他の種類の値ではないことが JavaScript エンジンに通知されるためです。

JSON.stringify(false) // "false"
JSON.stringify('false') // "\"false\""

上記のコードで内側に二重引用符がない場合、エンジンは将来復元するときに、元の値がブール値であるか文字列であるかを認識できません。

オブジェクトのプロパティが「未定義」、関数、または XML オブジェクトの場合、プロパティは「JSON.stringify()」によってフィルタリングされます。

var obj = {
  a:未定義、
  b: 関数 () {}
};

JSON.stringify(obj) // "{}"

上記のコードでは、オブジェクト obja プロパティは unknown で、b プロパティは関数であり、結果は JSON.stringify によってフィルタリングされます。

配列のメンバーが「未定義」、関数、または XML オブジェクトである場合、これらの値は「null」に変換されます。

var arr = [未定義, function () {}];
JSON.stringify(arr) // "[null,null]"

上記のコードでは、配列 arr のメンバーは 未定義 と関数であり、それらはすべて null に変換されます。

通常のオブジェクトは空のオブジェクトに変換されます。

JSON.stringify(/foo/) // "{}"

JSON.stringify() メソッドは、オブジェクトの走査不可能なプロパティを無視します。

var obj = {};
Object.defineProperties(obj, {
  'ふー': {
    値: 1、
    列挙可能: true
  }、
  'バー': {
    値: 2、
    列挙可能: false
  }
});

JSON.stringify(obj); // "{"foo":1}"

上記のコードでは、「bar」は「obj」オブジェクトの走査不可能なプロパティであり、「JSON.stringify」メソッドはこのプロパティを無視します。

2 番目のパラメータ

JSON.stringify() メソッドは、2 番目のパラメータとして配列を受け入れ、パラメータ オブジェクトのどのプロパティを文字列に変換する必要があるかを指定することもできます。

var obj = {
  'prop1': '値1',
  'prop2': '値2',
  'prop3': '値3'
};

var selectedProperties = ['prop1', 'prop2'];

JSON.stringify(obj, selectedProperties)
// "{"prop1":"value1","prop2":"value2"}"

上記のコードでは、JSON.stringify() メソッドの 2 番目のパラメーターは、2 つのプロパティ prop1prop2 のみが転送されることを指定しています。

このホワイトリストのような配列は、オブジェクトのプロパティに対してのみ有効であり、配列に対しては有効ではありません。

JSON.stringify(['a', 'b'], ['0'])
// "["a","b"]"

JSON.stringify({0: 'a', 1: 'b'}, ['0'])
// "{"0":"a"}"

上記のコードでは、2 番目のパラメーターは、JSON 形式が「0」属性のみを変換することを指定しています。実際、これは配列に対しては無効で、オブジェクトに対してのみ有効です。

2 番目のパラメータは、「JSON.stringify()」の戻り値を変更するために使用される関数にすることもできます。

関数 f(キー, 値) {
  if (値の種類 === "数値") {
    値 = 2 * 値;
  }
  戻り値;
}

JSON.stringify({ a: 1, b: 2 }, f)
// '{"a": 2,"b": 4}'

上記のコードの f 関数は、変換されるオブジェクトのキー名とキー値の 2 つのパラメーターを受け入れます。キーが数値の場合は「2」を掛け、それ以外の場合は変更せずに返します。

この処理関数はすべてのキーを再帰的に処理することに注意してください。

var obj = {a: {b: 1}};

関数 f(キー, 値) {
  console.log("["+ キー +"]:" + 値);
  戻り値;
}

JSON.stringify(obj, f)
// []:[オブジェクト オブジェクト]
//[a]:[オブジェクト オブジェクト]
//[b]:1
// '{"a":{"b":1}}'

上記のコードでは、オブジェクト objf 関数によって合計 3 回処理され、出力の最後の行が JSON.stringify() のデフォルトの出力になります。初めてキー名が空の場合、キー値はオブジェクト全体 obj になります。2 回目はキー名が a、キー値は {b: 1} になります。 b、キー値は 1 です。

再帰処理では、毎回処理されるオブジェクトは前回返された値になります。

var obj = {a: 1};

関数 f(キー, 値) {
  if (値の型 === 'オブジェクト') {
    {b: 2} を返します。
  }
  戻り値 * 2;
}

JSON.stringify(obj, f)
// "{"b": 4}"

上記のコードでは、「f」関数がオブジェクト「obj」を変更し、次に「JSON.stringify()」メソッドが変更されたオブジェクト「obj」を再帰的に処理します。

ハンドラーが「unknown」を返すか、戻り値がない場合、このプロパティは無視されます。

関数 f(キー, 値) {
  if (typeof(value) === "文字列") {
    未定義を返します。
  }
  戻り値;
}

JSON.stringify({ a: "abc", b: 123 }, f)
// '{"b": 123}'

上記のコードでは、「a」属性は処理後に「unknown」を返すため、この属性は無視されます。

3 番目のパラメータ

JSON.stringify() は、返された JSON 文字列の可読性を高めるために使用される 3 番目のパラメーターを受け入れることもできます。

デフォルトでは、単一行の文字列が返されますが、これは大きな JSON オブジェクトの可読性が非常に低くなります。 3 番目のパラメーターは、各属性が個別の行を占めるようにし、指定されたプレフィックス (10 文字以内) を各属性の前に追加します。

//デフォルトの出力
JSON.stringify({ p1: 1, p2: 2 })
// JSON.stringify({ p1: 1, p2: 2 })

// 分岐出力
JSON.stringify({ p1: 1, p2: 2 }, null, '\t')
// {
// "p1": 1,
// "p2": 2
// }

上記の例では、3 番目の属性 \t は各属性の前にタブ文字を追加し、それを別の行に表示します。

3 番目の属性が数値の場合、各属性の前に追加されるスペース (最大 10) を表します。

JSON.stringify({ p1: 1, p2: 2 }, null, 2);
/*
「{
  "p1": 1、
  「p2」: 2
}"
*/

パラメータオブジェクトの toJSON() メソッド

パラメータ オブジェクトにカスタム toJSON() メソッドがある場合、JSON.stringify() はこのメソッドの戻り値をパラメータとして使用し、元のオブジェクトの他のプロパティを無視します。

以下は通常のオブジェクトです。

var ユーザー = {
  名前: '三'、
  姓: '張'、

  フルネームを取得(){
    this.lastName + this.firstName を返します。
  }
};

JSON.stringify(ユーザー)
// "{"firstName":"三","lastName":"张","fullName":"张三"}"

次に、このオブジェクトに「toJSON()」メソッドを追加します。

var ユーザー = {
  名前: '三'、
  姓: '張'、

  フルネームを取得(){
    this.lastName + this.firstName を返します。
  }、

  toJSON: function () {
    戻る {
      名前: this.lastName + this.firstName
    };
  }
};

JSON.stringify(ユーザー)
// "{"名前":"張三"}"

上記のコードでは、JSON.stringify() はパラメータ オブジェクトに toJSON() メソッドがあることを検出し、元のオブジェクトの他のパラメータを無視して、このメソッドの戻り値をパラメータとして直接使用します。

Date オブジェクトには独自の toJSON() メソッドがあります。

var date = 新しい日付('2015-01-01');
date.toJSON() // "2015-01-01T00:00:00.000Z"
JSON.stringify(date) // ""2015-01-01T00:00:00.000Z""

上記のコードでは、JSON.stringify() は、Date オブジェクト インスタンスを処理していることを検出し、メソッドの戻り値をパラメーターとして使用して、このインスタンス オブジェクトの toJSON() メソッドを呼び出します。

toJSON() メソッドの応用例の 1 つは、通常のオブジェクトを文字列に自動的に変換することです。 JSON.stringify() はデフォルトでは通常のオブジェクトを変換できませんが、toJSON() メソッドを設定すると通常のオブジェクトを変換できるようになります。

var obj = {
  登録: /foo/
};

// toJSONメソッドが設定されていない場合
JSON.stringify(obj) // "{"reg":{}}"

//toJSONメソッドを設定する場合
RegExp.prototype.toJSON = RegExp.prototype.toString;
JSON.stringify(/foo/) // ""/foo/""

上記のコードは、通常のオブジェクトのプロトタイプに toJSON() メソッドをデプロイし、それを toString() メソッドにポイントします。したがって、JSON 形式に変換するとき、通常のオブジェクトは最初に toJSON() メソッドを呼び出します。それを文字列に変換し、JSON.stringify() メソッドによって処理されます。

JSON.parse()

JSON.parse() メソッドは、JSON 文字列を対応する値に変換するために使用されます。

JSON.parse('{}') // {}
JSON.parse('true') // true
JSON.parse('"foo"') // "foo"
JSON.parse('[1, 5, "false"]') // [1, 5, "false"]
JSON.parse('null') // null

var o = JSON.parse('{"名前": "張三"}');
o.name // チャン・サン

受信文字列が有効な JSON 形式でない場合、JSON.parse() メソッドはエラーを報告します。

JSON.parse("'String'") // 不正な単一引用符
// SyntaxError: 予期しないトークン ILLEGAL

上記のコードでは、二重引用符で囲まれた文字列は一重引用符で囲まれた文字列です。この一重引用符で囲まれた文字列は JSON 形式に準拠していないため、エラーが報告されます。

解析エラーを処理するには、「JSON.parse()」メソッドを「try...catch」コード ブロックに配置します。

試す {
  JSON.parse("'文字列'");
} キャッチ(e) {
  console.log('解析エラー');
}

JSON.parse() メソッドは 2 番目のパラメータとして処理関数を受け入れることができ、その使用法は JSON.stringify() メソッドと似ています。

関数 f(キー, 値) {
  if (key === 'a') {
    戻り値 + 10;
  }
  戻り値;
}

JSON.parse('{"a": 1, "b": 2}', f)
// {a: 11、b: 2}

上記のコードでは、JSON.parse() の 2 番目のパラメータは関数であり、キー名が a の場合、関数はキーの値に 10 を加算します。

JSON.parse()JSON.stringify() を次のように記述して一緒に使用すると、オブジェクトのディープ コピーを実現できます。

JSON.parse(JSON.stringify(obj))

上記の記述方法ではオブジェクトを深くクローンできますが、オブジェクト内に JSON を含めることはできません。 関数、通常のオブジェクト、日付オブジェクトなどのデータ型は許可されません。

参考リンク


作者: wangdoc

アドレス: https://wangdoc.com/

ライセンス: クリエイティブ・コモンズ 3.0