JavaScript と .NET での JavaScript オブジェクト表記 (JSON) の概要

 

JavaScript と .NET での JavaScript オブジェクト表記 (JSON) の概要

アティフ・アジズ、スコット・ミッチェル

2007 年 2 月

適用先:
   JSON
   Ajax

概要: この記事では、Ajax スタイルの Web アプリケーションに適した標準化されたデータ交換形式を提供する、オープンおよびテキストベースのデータ交換形式である JavaScript Object Notation (または JSON) について説明します。 (22 ページの印刷)

内容

はじめに
JavaScript でのリテラル表記について
JSON と XML の比較
JavaScript を使用した JSON メッセージの作成と解析
.NET Frameworkでの JSON の操作
まとめ
リファレンス

この記事のソース コードをダウンロードします

はじめに

リモート コンピューターと通信するアプリケーションを設計するときは、データ形式と交換プロトコルを選択する必要があります。 オープンで標準化されたさまざまなオプションがあり、理想的な選択はアプリケーションの要件と既存の機能によって異なります。 たとえば、SOAP ベースの Web サービスは、SOAP エンベロープ内にラップされた XML ペイロード内のデータを書式設定します。

XML は多くのアプリケーション シナリオで適切に機能しますが、他のアプリケーションの場合よりも低い欠点があります。 XML が理想的でないことが多いこのような領域の 1 つは、Ajax スタイルの Web アプリケーションです。 Ajax は、フル ページ ポストバックの代わりに、帯域外の軽量の Web サーバー呼び出しを使用して、よりわかりやすいユーザー エクスペリエンスを提供する対話型 Web アプリケーションを構築するために使用される手法です。 これらの非同期呼び出しは、JavaScript を使用してクライアントで開始され、データの書式設定、Web サーバーへの送信、返されたデータの解析と操作が含まれます。 ほとんどのブラウザーでは XML を構築、送信、解析できますが、JavaScript Object Notation (または JSON) は、Ajax スタイルの Web アプリケーションに適した標準化されたデータ交換形式を提供します。

JSON は、オープンでテキストベースのデータ交換形式です ( RFC 4627 を参照)。 XML と同様に、人間が判読できるプラットフォームに依存せず、実装の可用性が広がっています。 JSON 標準に従って書式設定されたデータは軽量であり、JavaScript の実装で簡単に解析できるため、Ajax Web アプリケーションに最適なデータ交換形式になります。 これは主にデータ形式であるため、JSON は単なる Ajax Web アプリケーションに限定されるものではなく、アプリケーションが構造化された情報をテキストとして交換または格納する必要があるほぼすべてのシナリオで使用できます。

この記事では、JSON 標準、JavaScript との関係、および XML との比較について説明します。 .NET 用のオープン ソース JSON 実装である Jayrock について説明し、JAVAScript と C# で JSON メッセージを作成および解析する例を示します。

JavaScript でのリテラル表記について

リテラルは、定数整数値 4 や文字列 "Hello, World" など、固定値を リテラルで 表現するためにプログラミング言語で使用されます。リテラルは、コントロール ステートメント内の条件の一部、関数の呼び出し時の入力パラメーター、変数の代入など、式が許可されているほとんどの言語で使用できます。 たとえば、次の C# コードと Visual Basic コードは、定数整数値 42 で変数 x を初期化します。

  
    int x = 42;  // C#
Dim x As Integer = 42  ' Visual Basic
  

異なるプログラミング言語では、さまざまな型のリテラルを使用できます。 ほとんどのプログラミング言語では、整数、浮動小数点数、文字列、ブール型などのスカラー型のリテラルが少なくともサポートされています。 JavaScript の興味深い点は、スカラー型に加えて、配列やオブジェクトなどの構造化型のリテラルもサポートすることです。 この機能により、配列とオブジェクトのオンデマンド作成と初期化のための簡潔な構文が可能になります。

JavaScript の配列リテラルは、0 個以上の式で構成され、各式は配列の要素を表します。 配列要素は角かっこ ([]) で囲み、コンマで区切られます。 次の例では、7 つの大陸の名前を保持する 7 つの文字列要素を含む配列を リテラル で定義します。

  
    var continents = ["Europe", "Asia", "Australia", "Antarctica", "North
 America", "South America", "Africa"];
alert(continents[0] + " is one of the " + continents.length + "
 continents.");
  

これを、リテラル表記なしで JavaScript で配列を作成および初期化する方法と比較します。

  
    var continents = new Array();
continents[0] = "Europe";
continents[1] = "Asia";
continents[2] = "Australia";
continents[3] = "Antarctica";
continents[4] = "North America";
continents[5] = "South America";
continents[6] = "Africa";
  

オブジェクト リテラルは、オブジェクトのメンバーとその値を定義します。 オブジェクトのメンバーと値の一覧は中かっこ ({}) で囲まれており、各メンバーはコンマで区切られます。 各メンバー内では、名前と値はコロン (:) で区切られます。 次の例では、オブジェクトを作成し、それぞれの値が "123 Anywhere St."、"Springfield"、および "99999" の Address、CityPostalCode という名前の 3 つのメンバーで初期化されます。

  
    var mailingAddress = { 
     "Address"    :   "123 Anywhere St.", 
     "City"       :   "Springfield", 
     "PostalCode" :   99999
};
alert("The package will be shipped to postal code " +
 mailingAddress.PostalCode);
  

これまでに示した例では、配列リテラルとオブジェクト リテラル内で文字列リテラルと数値リテラルを使用する方法を示しています。 また、配列要素とオブジェクト メンバー値がオブジェクトリテラルと配列リテラルを使用できるように、再帰的に表記を使用してグラフ全体を表現することもできます。 たとえば、次のスニペットは、配列がメンバー (PhoneNumbers) として配列を持つオブジェクトを示しています。このオブジェクトはオブジェクトのリストで構成されています。

  
    var contact = {
     "Name": "John Doe",
     "PermissionToCall": true,
     "PhoneNumbers": [ 
       {
           "Location": "Home",
           "Number": "555-555-1234"
       },
       {
           "Location": "Work",
           "Number": "555-555-9999 Ext. 123"
       }
     ]
};
if (contact.PermissionToCall)
{
  alert("Call " + contact.Name + " at " + contact.PhoneNumbers[0].Number);
}
  

メモ JavaScript のリテラルサポートの詳細については、 Core JavaScript 1.5 ガイド「リテラル」セクションを参照してください

JavaScript リテラルから JSON へ

JSON は、JavaScript のリテラル オブジェクト表記のサブセットから作成されたデータ交換形式です。 リテラル値に対して JavaScript で受け入れられる構文は非常に柔軟ですが、JSON の規則がはるかに厳しい点に注意することが重要です。 たとえば、JSON 標準に従って、オブジェクト メンバーの名前は有効な JSON 文字列である 必要があります 。 JSON 内の文字列は引用符で囲む 必要があります 。 一方、JavaScript では、メンバー名が予約 JavaScript キーワードと競合しない限り、オブジェクト メンバー名を引用符またはアポストロフィで区切ったり、引用符を完全に省略したりできます。 同様に、JSON の配列要素またはオブジェクト メンバー値は、非常に限られたセットに制限されます。 ただし、JavaScript では、配列要素とオブジェクト メンバー値は、関数呼び出しや定義など、有効な JavaScript 式をほとんど参照できます。

JSON の魅力はシンプルさにあります。 JSON 標準に従って書式設定されたメッセージは、1 つの最上位レベルのオブジェクトまたは配列で構成されます。 配列要素とオブジェクト値には、オブジェクト、配列、文字列、数値、ブール値 (true と false)、または null を指定できます。 簡単に言うと、これは JSON 標準です。 それは非常に単純です。 標準のより正式な説明については、 www.json.org または RFC 4627 を参照してください。

JSON の痛い点の 1 つは、日付/時刻リテラルがない点です。 多くの人々は、最初にJSONに遭遇したときにこれを学ぶことに驚き、がっかりしています。 日付/時刻リテラルがない場合の簡単な説明 (慰めか否か) は、JavaScript に日付と時刻の値のサポートが完全に Date オブジェクトを通じて提供されることです。 JSON をデータ形式として使用するほとんどのアプリケーションでは、通常、日付と時刻の値を表すために文字列または数値を使用する傾向があります。 文字列を使用する場合、通常は ISO 8601 形式であると想定できます。 代わりに数値を使用する場合、通常、エポックは 1970 年 1 月 1 日 (UTC) の午前 0 時として定義されるため、値は世界協定時刻 (UTC) のミリ秒数を意味します。 繰り返しますが、これは単なる規則であり、JSON 標準の一部ではありません。 別のアプリケーションとデータを交換する場合は、そのドキュメントを確認して、JSON リテラル内の日付と時刻の値がどのようにエンコードされるかを確認する必要があります。 たとえば、Microsoft の ASP.NET AJAX では、説明されている規則のいずれも使用しません。 代わりに、.NET DateTime 値を JSON 文字列としてエンコードします。文字列の内容は \/Date(ticks)\/ で、 ティック はエポック (UTC) 以降のミリ秒を表します。 そのため、1989 年 11 月 29 日午前 4 時 55 分 30 分 (UTC) は "\/Date(628318530718)\/" としてエンコードされます。 このかなり工夫されたエンコードの選択の背後にあるいくつかの根拠については、「AJAX の JSON 日時文字列 ASP.NET 内部」を参照してください。

JSON と XML の比較

JSON と XML の両方を使用して、テキストベースの人間が判読できるデータ交換形式で、ネイティブのメモリ内オブジェクトを表すことができます。 さらに、2 つのデータ交換形式は同型です。一方の形式のテキストを指定すると、同等の形式が他方で考えられます。 たとえば、 Yahoo!のパブリックにアクセス可能な Web サービスのいずれかを呼び出すときに、応答を XML または JSON として書式設定する必要があるかどうかをクエリ文字列パラメーターを使用して指定できます。 したがって、データ交換形式を決定する場合、どちらか一方を銀色の箇条書きとして選択する単純な問題ではなく、特定のアプリケーションに最適な選択をする 特性 を持つ形式を指定します。 たとえば、XML はドキュメント テキストのマーキングに根ざしており、(XHTML で明らかなように) その空間で非常によく輝く傾向があります。 一方、JSON はプログラミング言語の型と構造に根ざしているため、構造化データを交換するためのより自然で簡単に利用できるマッピングが提供されます。 これら 2 つの開始点を超えて、次の表は、XML と JSON の主な特性を理解し、比較するのに役立ちます。

XML と JSON の主な特性の違い

特徴 XML JSON
データ型 データ型の概念を提供しません。 型情報を追加するには 、XML スキーマ に依存する必要があります。 スカラー データ型と、配列とオブジェクトを介して構造化データを表現する機能を提供します。
配列のサポート 配列は、たとえば、配列の内容を内部要素としてモデル化する外部プレースホルダー要素を使用して、規則によって表現する必要があります。 通常、外側の要素は、内部要素に使用される名前の複数形を使用します。 ネイティブ配列のサポート。
オブジェクトのサポート オブジェクトは、多くの場合、属性と要素を混在させて表現する必要があります。 ネイティブ オブジェクトのサポート。
Null のサポート XML インスタンス ドキュメント内の要素に xsi:nil を使用し、対応する名前空間をインポートする必要があります。 null 値をネイティブに認識します。
コメント ネイティブ サポート。通常は API を介して利用できます。 サポートされていません。
名前空間 名前空間をサポートし、ドキュメントを組み合わせる際に名前の競合のリスクを排除します。 名前空間を使用すると、既存の XML ベースの標準を安全に拡張することもできます。 名前空間の概念はありません。 名前付けの競合は、通常、オブジェクトを入れ子にしたり、オブジェクト メンバー名にプレフィックスを使用したりすることによって回避されます (前者は実際には推奨されます)。
書式設定の決定 複合」を参照してください。 アプリケーションの種類を XML 要素と属性にマップする方法を決定するには、より多くの労力が必要です。 要素中心のアプローチと属性中心のアプローチのどちらが優れているかを問わず、熱い議論を生み出すことができます。 シンプル。 アプリケーション データのより直接的なマッピングを提供します。 唯一の例外は、日付/時刻リテラルがない場合があります。
サイズ ドキュメントのサイズは長い傾向があります。特に、要素中心の書式設定方法を使用する場合です。 構文は非常に簡潔で、書式設定されたテキストが生成されます。この場合、ほとんどの領域は表されたデータによって使用されます (正しくそう)。
JavaScript での解析 テキストを JavaScript オブジェクトにマップするには、XML DOM 実装と追加のアプリケーション コードが必要です。 テキストを解析するために追加のアプリケーション コードは必要ありません。では、JavaScript の eval 関数を 使用できます。
学習曲線 一般に、 XPath、XML スキーマ、 XSLTXML 名前空間DOM など、複数のテクノロジを一同に使用する必要があります。 JavaScript やその他の動的プログラミング言語のバックグラウンドを持つ開発者に既に知られている非常にシンプルなテクノロジ スタック。

JSON は比較的新しいデータ交換形式であり、XML が現在享受している導入やベンダーサポートの年数はありません (ただし、JSON はすぐに追いついています)。 次の表は、XML および JSON スペースの現在の状態を示しています。

XML と JSON の違いをサポートする

サポート XML JSON
ツール 多くの業界ベンダーから広く利用できる成熟したツールセットを楽しんでいます。 エディターやフォーマッタなどの豊富なツール サポートは、ほとんどサポートされていません。
[Microsoft .NET Framework] .NET Frameworkのバージョン 1.0 以降、非常に優れた成熟したサポート。 XML のサポートは、基本クラス ライブラリ (BCL) の一部として利用できます。 アンマネージド環境では、MSXMLがあります。 AJAX の一部としての初期実装を除き、これまでにはありません ASP.NET
プラットフォームと言語 パーサーとフォーマッタは、多くのプラットフォームと言語 (商用およびオープンソース実装) で広く利用できます。 パーサーとフォーマッタは、多くのプラットフォームと多くの言語で既に利用できます。 参照の適切なセットについては、 json.org を参照してください。 現在のほとんどの実装は、オープンソースプロジェクトである傾向があります。
統合言語 業界ベンダーは現在、言語内で 文字通り サポートを試しています。 詳細については 、Microsoft の LINQ プロジェクト を参照してください。 JavaScript/ECMAScript でのみネイティブにサポートされています。

メモ どちらのテーブルも、比較ポイントの包括的な一覧ではありません。 両方のデータ形式を比較できる角度がさらにありますが、これらの重要なポイントは初期印象を構築するのに十分であると感じました。

JavaScript を使用した JSON メッセージの作成と解析

データ交換形式として JSON を使用する場合、2 つの一般的なタスクは、ネイティブおよびインメモリ表現を JSON テキスト表現に変換し、その逆を行います。 残念ながら、執筆時点では、JavaScript には、特定のオブジェクトまたは配列から JSON テキストを作成するための組み込み関数は用意されていません。 これらのメソッドは、2007 年に ECMAScript 標準の第 4 版に含まれる予定です。 これらの JSON 書式設定関数が正式に JavaScript に追加され、一般的な実装全体で広く使用できるようになるまで、ダウンロード http://www.json.org/json.js可能な参照実装スクリプトを使用します。

この記述時の最新のイテレーションでは、 www.json.org のjson.js スクリプトは、配列、文字列、ブール型、オブジェクト、およびその他の JavaScript 型 に toJSONString() 関数を追加します。 スカラー型 (Number や Boolean など ) の toJSONString() 関数は、インスタンス値の文字列表現のみを返す必要があるため、非常に単純です。 たとえば、ブール型の toJSONString() 関数は、値が true の場合は文字列 "true" を返し、それ以外の場合は "false" を返します。 配列型とオブジェクト型の toJSONString() 関数の方が興味深いです。 配列インスタンスの場合、各包含要素の toJSONString() 関数が順番に呼び出され、結果はコンマで連結され、各結果が区切られます。 角かっこで囲まれた最終的な出力。 同様に、Object インスタンスの場合、各メンバーが列挙され、その toJSONString() 関数が呼び出されます。 メンバー名とその値の JSON 表現は、中央にコロンと連結されます。各メンバー名と値のペアはコンマで区切られ、出力全体が中かっこで囲まれます。

toJSONString() 関数の結果として、任意の型を 1 回の関数呼び出しで JSON 形式に変換できます。 次の JavaScript では、Array オブジェクトを作成し、説明のために詳細メソッドと非リテラル メソッドを使用して意図的に 7 つの String 要素を追加します。 次に、配列の JSON 表現を表示します。

  
    // josn.js must be included prior to this point

var continents = new Array();
continents.push("Europe");
continents.push("Asia");
continents.push("Australia");
continents.push("Antarctica");
continents.push("North America");
continents.push("South America");
continents.push("Africa");

alert("The JSON representation of the continents array is: " +
 continents.toJSONString());
  

Bb299886.intro_to_json01(en-us,MSDN.10).gif

図 1. toJSONString() 関数は、JSON 標準に従って書式設定された配列を出力します。

JSON テキストの解析はさらに簡単です。 JSON は単なる JavaScript リテラルのサブセットであるため、ソース JSON テキストを JavaScript ソース コードとして扱う eval(expr) 関数, を使用して、メモリ内表現に解析できます。 eval 関数は、有効な JavaScript コードの文字列を入力として受け入れ、式を評価します。 その結果、JSON テキストをネイティブ表現に変換するために必要なのは、次の 1 行のコードです。

  
    var value = eval( "(" + jsonText + ")" );
  

メモ 余分なかっこを使用すると、 eval はソース入力を無条件に式のように扱います。 これは、オブジェクトにとって特に重要です。 文字列 "{}" (空のオブジェクトを意味する) などのオブジェクトを定義する JSON テキストを含む文字列で eval を呼び出そうとすると、解析された結果として未定義が返されます。 かっこを使用すると、JavaScript パーサーでは、ステートメント ブロックを定義する中かっこではなく、最上位レベルの中かっこが Object インスタンスのリテラル表記として表示されます。 なお、最上位項目が配列である場合も、 eval("[1,2,3]") のように同じ問題は発生しません。 ただし、統一性のために、JSON テキストは常に eval を呼び出す前にかっこで囲む必要があり、ソースの解釈方法にあいまいさはありません。

リテラル表記を評価するときに、リテラル構文に対応するインスタンスが返され、 に割り当てられます。 次の例では、 eval 関数を使用して配列のリテラル表記を解析し、結果の配列を変数 大陸に割り当てます。

  
    var arrayAsJSONText = '["Europe", "Asia", "Australia", "Antarctica",
 "North America", "South America", "Africa"]';
var continents = eval( arrayAsJSONText );
alert(continents[0] + " is one of the " + continents.length + "
 continents.");
  

もちろん、実際には、評価された JSON テキストは、上記のケースのようにハードコーディングされるのではなく、外部ソースから取得されます。

eval 関数は、渡された式を盲目的に評価します。 したがって、信頼できないソースには、危険な可能性のある JavaScript と共に、または JSON データを構成するリテラル表記に組み込まれる可能性があります。 ソースを信頼できないシナリオでは、 parseJSON() 関数 (json.jsで見つかった) を使用して JSON テキストを解析することを強くお勧めします。

  
    // Requires json.js
var continents = arrayAsJSONText.parseJSON();
  

parseJSON() 関数では eval も使用されますが、arrayAsJSONText に含まれる文字列が JSON テキスト標準に準拠している場合にのみ使用されます。 これは、賢い正規表現テストを使用して行います。

.NET Frameworkでの JSON の操作

JSON テキストは、その魅力の一部である JavaScript コードから簡単に作成および解析できます。 ただし、ASP.NET Web アプリケーションで JSON を使用する場合、サーバー側のコードは Visual Basic または C# で記述される可能性が最も高いため、JavaScript のサポートはブラウザーのみが利用できます。

ASP.NET 用に設計されたほとんどの Ajax ライブラリは、プログラムによる JSON テキストの作成と解析のサポートを提供します。 したがって、.NET アプリケーションで JSON を操作するには、これらのライブラリのいずれかを使用することを検討してください。 オープン ソースとサード パーティのオプションが多数あり、Microsoft には AJAX という名前の独自の Ajax ライブラリ ASP.NET もあります。

この記事では、共同編集者 Atif Aziz によって作成された Microsoft .NET Frameworkの JSON のオープンソース実装である Jayrock を使用する例について説明します。 次の 3 つの理由から、AJAX を ASP.NET の代わりに Jayrock を使用することを選択しました。

  • Jayrock はオープンソースであるため、必要に応じて拡張またはカスタマイズできます。
  • Jayrock は、ASP.NET 1.x、2.0、Mono アプリケーションで使用できますが、ASP.NET AJAX はバージョン 2.0 のみを対象 ASP.NET。
  • Jayrock のスコープは JSON と JSON-RPC に制限されており、前者がこの記事の主な焦点です。 ASP.NET AJAX には JSON テキストの作成と解析に関するいくつかのサポートが含まれていますが、主な目的は、ASP.NET でエンド ツー エンドの Ajax スタイルの Web アプリケーションを構築するための豊富なプラットフォームを提供することです。 メインフォーカスが JSON の場合、余分なベルやホイッスルが気を散らす可能性があります。

Jayrock を使用した .NET での JSON の操作は、.NET Frameworkの XmlWriterXmlReaderXmlSerializer クラスを使用して XML を操作するのと似ています。 Jayrock で見つかった JsonWriterJsonReaderJsonTextWriterJsonTextReader のクラスは、.NET Framework クラス XmlWriterXmlReader、XmlTextWriter、および XmlTextReader のセマンティクスを模倣します。 これらのクラスは、低およびストリーム指向のレベルで JSON とインターフェイスする場合に役立ちます。 これらのクラスを使用すると、一連のメソッド呼び出しを通じて JSON テキストを作成または解析できます。 たとえば、 JsonWriter クラス メソッド WriteNumber(number) を使用すると、JSON 標準 に従って 数値の適切な文字列表現が書き出されます。 JsonConvert クラスは、.NET 型と JSON の間で変換するための Export メソッドと Import メソッドを提供します。 これらのメソッドは、それぞれシリアル化逆シリアル化XmlSerializer クラス メソッドで見られるのと同様の機能を提供します。

JSON テキストの作成

次のコードは、 JsonTextWriter クラスを使用して、大陸の文字列配列の JSON テキストを作成する方法を示しています。 この JSON テキストは、コンストラクターに渡された TextWriter インスタンスに送信されます。これは、この例のコンソールからの出力ストリームになります (ASP.NET では、代わりに Response.Output を使用できます)。

  
    using (JsonTextWriter writer = JsonTextWriter(Console.Out))
{
    writer.WriteStartArray();
    writer.WriteString("Europe");
    writer.WriteString("Asia");
    writer.WriteString("Australia");
    writer.WriteString("Antarctica");
    writer.WriteString("North America");
    writer.WriteString("South America");
    writer.WriteString("Africa");
    writer.WriteEndArray();
}
  

WriteStartArrayWriteStringWriteEndArray のメソッドに加えて、JsonWriter クラスには、WriteNumberWriteBooleanWriteNull などの他の JSON 値型を書き込むためのメソッドが用意されています。 WriteStartObjectWriteEndObject、および WriteMember メソッドは、オブジェクトの JSON テキストを作成します。 次の例では、「JavaScript でのリテラル表記について」セクションで調べた連絡先オブジェクトの JSON テキストを作成する方法を示します。

private static void WriteContact()
{
    using (JsonWriter w = new JsonTextWriter(Console.Out))
    {
        w.WriteStartObject();              // {
        w.WriteMember("Name");             //   "Name" : 
        w.WriteString("John Doe");         //     "John Doe",
        w.WriteMember("PermissionToCall"); //   "PermissionToCall" :
        w.WriteBoolean(true);              //     true,
        w.WriteMember("PhoneNumbers");     //   "PhoneNumbers" :
        w.WriteStartArray();               //   [ 
        WritePhoneNumber(w,                //     { "Location": "Home",
            "Home"                         //       "Number": 
            "555-555-1234");               //         "555-555-1234" },
        WritePhoneNumber(w,                //     { "Location": "Work",
            "Work",                        //       "Number": 
            "555-555-9999");               //       "555-555-9999" }
        w.WriteEndArray();                 //   ]
        w.WriteEndObject();                // }
    }
}

private static void WritePhoneNumber(JsonWriter w, string location,
    string number)
{
    w.WriteStartObject();      //  {
    w.WriteMember("Location"); //      "Location" : 
    w.WriteString(location);   //          "...", 
    w.WriteMember("Number");   //      "Number" :
    w.WriteString(number);     //          "..."
    w.WriteEndObject();        //  }
}

JsonConvert クラスの Exportおよび ExportToString メソッドを使用して、指定した .NET 型を JSON テキストにシリアル化できます。 たとえば、 JsonTextWriter クラスを使用して 7 つの大陸の配列の JSON テキストを手動で構築するのではなく、 JsonConvert.ExportToString を次に呼び出すと、同じ結果が生成されます。

string[] continents = {
      "Europe", "Asia", "Australia", "Antarctica", "North America", 
      "South America", "Africa"
};
string jsonText = JsonConvert.ExportToString(continents);

JSON テキストの解析

JsonTextReader クラスには、JSON テキストのトークンを読み取り中のコアと共に解析するためのさまざまなメソッドが用意されています。 Read メソッドが呼び出されるたびに、パーサーは次のトークン (文字列値、数値、オブジェクト メンバー名、配列の先頭など) を使用します。 必要に応じて、現在のトークンの解析されたテキストに Text プロパティを使用してアクセスできます。 たとえば、リーダーがブールデータに置かれている場合、 Text プロパティは実際の解析値に応じて "true" または "false" を返します。

次のサンプル コードでは 、JsonTextReader クラスを使用して、7 つの大陸の名前を含む文字列配列の JSON テキスト表現を解析します。 文字 "A" で始まる各大陸がコンソールに送信されます。

  
    string jsonText = @"[""Europe"", ""Asia"", ""Australia"", ""Antarctica"",
 ""North America"", ""South America"", ""Africa""]";

using (JsonTextReader reader = new JsonTextReader(new
 StringReader(jsonText)))
{
    while (reader.Read())
    {
        if (reader.TokenClass == JsonTokenClass.String &&
            reader.Text.StartsWith("A"))
        {
            Console.WriteLine(reader.Text);
        }
    }
}
  

メモ Jayrock の JsonTextReader クラスは、かなりリベラルな JSON テキスト パーサーです。 RFC 4627 に記載されている規則に従って、有効な JSON テキストと見なされるよりもはるかに多くの構文が実際に許可されます。 たとえば、 JsonTextReader クラスを使用すると、JavaScript の場合と同様に、単一行と複数行のコメントを JSON テキスト内に表示できます。 1 行のコメントはスラッシュ (//) で始まり、複数行のコメントはスラッシュスター (/*) で、末尾はスタースラッシュ (*/) になります。 1 行のコメントは、Unix スタイルの構成ファイルで一般的なハッシュ/ポンド記号 (#) で始まることもあります。 すべてのインスタンスで、コメントはパーサーによって完全にスキップされ、API を介して公開されることはありません。 また、JavaScript と同様に、 JsonTextReader では JSON 文字列をアポストロフィ (') で区切ることもできます。 パーサーは、配列のオブジェクトまたは要素の最後のメンバーの後に余分なコンマを許容することもできます。

これらのすべての追加でも、 JsonTextReader は準拠しているパーサーです。 一方、JsonTextWriter では、厳密な標準準拠の JSON テキストのみが生成されます。 これは、多くの場合、堅牢性プリンシパルとして造られたものに続きます。これは、「あなたが行うことに保守的である。他の人から受け入れる内容でリベラルである。

JSON テキストを .NET オブジェクトに直接変換するには、 JsonConvert クラスのインポート メソッドを使用して、出力の種類と JSON テキストを指定します。 次の例は、文字列の JSON 配列を .NET 文字列配列に変換する方法を示しています。

string jsonText = @"[""Europe"", ""Asia"", ""Australia"", ""Antarctica"",
 ""North America"", ""South America"", ""Africa""]";

string[] continents = (string[]) JsonConvert.Import(typeof(string[]),
 jsonText);

RSS XML フィードを受け取り、 XmlSerializer を使用して .NET 型に逆シリアル化し、 JsonConvert を使用してオブジェクトを JSON テキストに変換する変換のより興味深い例を次に示します (実質的に XML の RSS を JSON テキストに変換します)。

XmlSerializer serializer = new XmlSerializer(typeof(RichSiteSummary));
RichSiteSummary news;

// Get the MSDN RSS feed and deserialize it...

using (XmlReader reader = XmlReader.Create("https://msdn.microsoft.com/rss.xml"))
    news = (RichSiteSummary) serializer.Deserialize(reader);

// Export the RichSiteSummary object as JSON text, emitting the output to
// Console.Out.

using (JsonTextWriter writer = new JsonTextWriter(Console.Out))
    JsonConvert.Export(news, writer);

メモRichSiteSummary とその関連する型の定義については、この記事に付属するサンプルを参照してください。

ASP.NET での JSON の使用

JavaScript で JSON を操作する方法と、Jayrock を使用して.NET Framework内から操作する方法を見て、この知識をすべて適用できる場所と方法の実用的な例に目を向けます。 ASP.NET 2.0 のクライアント スクリプト コールバック機能を検討すると、Web ブラウザーから ASP.NET ページ (またはページ上の特定のコントロール) への帯域外呼び出しのプロセスが簡略化されます。 一般的なコールバック シナリオでは、ブラウザー内のクライアント側スクリプトがパッケージ化され、サーバー側メソッドによる何らかの処理のために Web サーバーにデータが送信されます。 サーバーから応答データを受信した後、クライアントはそれを使用してブラウザーの表示を更新します。

メモ詳細については、MSDN マガジンの記事「ASP.NET 2.0 のスクリプト コールバック」を参照してください。

クライアント コールバック シナリオの課題は、クライアントとサーバーが文字列を前後にのみ送信できることです。 したがって、交換する情報は、送信される前にネイティブのメモリ内表現から文字列に変換され、受信時に文字列からネイティブのメモリ内表現に解析される必要があります。 ASP.NET 2.0 のクライアント スクリプト コールバック機能では、交換されたデータに対して特定の文字列形式は必要ありません。また、ネイティブのインメモリ表現と文字列表現の間で変換するための組み込み機能も提供しません。選択したデータ交換形式に基づいて変換ロジックを実装するのは開発者の責任です。

次の例では、クライアント スクリプト コールバック シナリオで JSON をデータ交換形式として使用する方法を示します。 特に、この例は Northwind データベースのデータを使用してドロップダウン リスト内のカテゴリの一覧を提供する ASP.NET ページで構成されています。選択したカテゴリの製品は箇条書きで表示されます (図 3 を参照)。 クライアント側でドロップダウン リストが変更されるたびに、1 つの要素が選択された CategoryID である配列を渡すコールバックが行われます。

メモ JSON 標準では、JSON テキストにオブジェクトまたは配列をルートとして含める必要があるため、選択した CategoryID を ( CategoryID だけでなく) 唯一の要素として含む配列を渡しています。 もちろん、クライアントは JSON テキストをサーバーに渡す必要はありません。この例では、選択した CategoryID だけを文字列として渡すことができます。 ただし、コールバックの要求メッセージと応答メッセージの両方で JSON テキストを送信する方法を示したいと考えました。

Page_Load イベント ハンドラーの次のコードは、Categories DropDownList Web コントロールが変更されたときに GetProductsForCategory 関数が呼び出され、選択したドロップダウン リスト値を渡すように構成します。 この関数は、渡されたドロップダウン リストの値が 0 より大きい場合に、クライアント スクリプト コールバックを開始します。

  
    // Add client-side onchange event to drop-down list
Categories.Attributes["onchange"] = "Categories_onchange(this);";

// Generate the callback script
string callbackScript = ClientScript.GetCallbackEventReference(
    /* control        */ this, 
    /* argument       */ "'[' + categoryID + ']'", 
    /* clientCallback */ "showProducts", 
    /* context        */ "null");

// Add the Categories_onchange function
ClientScript.RegisterClientScriptBlock(GetType(),
"Categories_onchange", @"
    function Categories_onchange(sender)
    {
        clearResults();

        var categoryID = sender.value;            
        if (categoryID > 0)
        {
            " + callbackScript + @"
        }
    }", true);
  

コールバックを呼び出す JavaScript コードを生成するために使用される ClientScriptManager クラスの GetCallBackEventReference メソッドには、次のシグネチャがあります。

  
    public string GetCallbackEventReference (
    Control control,
    string argument,
    string clientCallback,
    string context,
)
  

引数パラメーターは、コールバック中にクライアントから Web サーバーに送信されるデータを指定し、clientCallback パラメーターは、コールバックの完了時に呼び出すクライアント側関数の名前 (showProducts) を指定します。 GetCallBackEventReference メソッド呼び出しでは、次の JavaScript コードが生成され、レンダリングされたマークアップに追加されます。

  
    WebForm_DoCallback('__Page','[' + categoryID + 
']',showProducts,null,null,false)
  

'[' + categoryID + ']' は、コールバック中にサーバーに渡される値 (単一の要素である categoryID を持つ配列) であり、 showProducts はコールバックが返されるときに実行される JavaScript 関数です。

サーバー側では、コールバックに応答して実行されるメソッドは、Jayrock の JsonConvert クラスを使用して受信 JSON テキストを解析し、送信 JSON テキストの書式を設定します。 特に、選択したカテゴリに関連付けられている製品の名前が取得され、文字列配列として返されます。

  
    // Deserialize the JSON text into an array of integers
int[] args = (int[]) JsonConvert.Import(typeof(int[]), eventArgument);

// Read the selected CategoryID from the array
int categoryID = args[0];

// Get products based on categoryID 

  NorthwindDataSet.ProductsRow[] rows = 
Northwind.Categories.FindByCategoryID(categoryID).GetProductsRows();

// Load the names into a string array
string[] productNames = new string[rows.Length];
for (int i = 0; i < rows.Length; i++)
{
    productNames[i] = rows[i].ProductName;
}

// Serialize the string array as JSON text and return it to the client
return JsonConvert.ExportToString(productNames);

メモJsonConvert クラスは 2 回使用されます。eventArgument の JSON テキストを整数の配列に変換してから、文字列配列 productNames を JSON テキストに変換してクライアントに返します。 または、 ここで JsonReader クラスと JsonWriter クラスを使用することもできますが、関連するデータが比較的小さく、既存の型に簡単にマップされている場合、 JsonConvert は同じジョブをかなり適切に実行します。

サーバー側からデータが返されると、 GetCallBackEventReference メソッドから指定された JavaScript 関数が呼び出され、戻り値が渡されます。 この JavaScript メソッド showProducts はdiv> 要素 ProductOutput を<参照することから始まります。 その後、JSON 応答を解析し、配列要素ごとにリスト 項目を含む順序なしリストを動的に追加します。 選択したカテゴリに対して製品が返されない場合は、代わりに対応するメッセージが表示されます。

function showProducts(arg, context)
{
    // Dump the JSON text response from the server.

    document.forms[0].JSONResponse.value = arg;
    
    // Parse JSON text returned from callback.

    var categoryProducts = eval("(" + arg + ")");

    // Get a reference to the <div> ProductOutput.
    
    var output = document.getElementById("ProductOutput");

    // If no products for category, show message.
    
    if (categoryProducts.length == 0)
    {
        output.appendChild(document.createTextNode(
            "There are no products for this category..."));
    }
    else
    {
        // There are products, display them in an unordered list. 
        
        var ul = document.createElement("ul");
        
        for (var i = 0; i < categoryProducts.length; i++)
        {
            var product = categoryProducts[i];
            var li = document.createElement("li");
            li.appendChild(document.createTextNode(product));
            ul.appendChild(li);
        }
        
        output.appendChild(ul);
    }
}

図 2 は一連のイベントを示し、図 3 はこの例の動作を示しています。完全なコードは、この記事のダウンロードに含まれています。

Bb299886.intro_to_json02(en-us,MSDN.10).gif

図 2: クライアントは、選択した CategoryID を配列内の 1 つの要素として送信し、サーバーは関連付けられた製品名の配列を返します。

Bb299886.intro_to_json03(en-us,MSDN.10).gif

図 3: 製品は、選択したカテゴリ内の箇条書きで表示されます。

まとめ

JSON は、JavaScript プログラミング言語のリテラル表記のサブセットに基づく、軽量のテキスト ベースのデータ交換形式です。 アプリケーション データ構造の簡潔なエンコードが提供され、通常は、Ajax スタイルの Web アプリケーションなど、データを交換するアプリケーションの一方または両方で JavaScript 実装を使用できるシナリオで使用されます。 JSON の魅力は、理解、導入、実装のシンプルさにあります。 JSON には、JavaScript や、豊富なリテラル表記 (Python や Ruby など) に対する同様のサポートを備えた他のプログラミング言語に既に精通している開発者にとって、学習曲線はほとんどありません。 JavaScript コードで JSON テキストを解析するには、 eval 関数を呼び出すだけで実行できます。JSON テキストの作成は、次に示すjson.jsスクリプトを使用して簡単に http://www.json.org/json.js作成できます。

すべての主要なプラットフォームとフレームワークで JSON を操作するためのライブラリが数多く用意されています。 この記事では、.NET アプリケーションで JSON テキストを作成および解析するためのオープンソース ライブラリである Jayrock について説明しました。 Jayrock は、ASP.NET 1.x、2.0、Mono アプリケーションで使用できます。 ASP.NET AJAX は同様の JSON 機能を提供しますが、ASP.NET 2.0 アプリケーションに対してのみ提供されます。

ハッピープログラミング!

リファレンス

Ajax または AJAX?

Ajax という用語は、最初は Jesse James Garrett によって造語され、Web アプリケーションのスタイルと、高度にインタラクティブな Web アプリケーションの作成に関連する一連のテクノロジについて説明しました。 従来、Ajax という用語は頭字語 AJAX として Web の周囲に広がり、非同期 JavaScript と XML を意味します。 しかし、時間の経過と共に、ほとんどの実装はよりシンプルで効率的な代替手段として JSON に切り替えられていたため、AJAX の "X" はバックグラウンドで Web サーバーとの通信に使用される基になるデータ形式をあまり表していないことに気付きました。 したがって、AJAJのような少し舌のツイスターである代わりの頭字語を思い付くのではなく、頭字語は一般的に頭字語AJAXではなくAjaxの用語を支持して廃止されています。

この執筆時点では、"AJAX" と "Ajax" が混在して広く使用されており、1 つと同じことを意味することを期待しています。 この記事では、"Ajax the term" に悩まされています。しかし、Ajaxスタイルのアプリケーションを可能にするフレームワークを提供する商用製品は、略語形式を使用して、同様の名前の洗浄剤製品と区別し、潜在的な商標または法的紛争を回避する傾向があります。

ASP.NET AJAX: JSON の日付と時刻の文字列内

ASP.NET の AJAX JSON シリアライザーは、DateTime インスタンスを JSON 文字列としてエンコードします。 プレリリース サイクル中、ASP.NET AJAX では "@ticks@" という形式が使用されました。ここで、ティックは 1970 年 1 月 1 日以降のミリ秒数を世界協定時刻 (UTC) で表します。 1989 年 11 月 29 日午前 4:55:30 のような UTC の日付と時刻は、"@62831853071@" と書き出されます。単純で簡単ですが、この形式では、シリアル化された日付と時刻の値と、シリアル化された日付のように見えるが、1 つとして逆シリアル化されることを意図していない文字列を区別することはできません。 その結果、ASP.NET AJAX チームは、"\/Date(ticks)\/" 形式を採用して、この問題に対処するための最終リリースを変更しました。

新しい形式は、誤解釈の可能性を減らすために小さなトリックに依存しています。 JSON では、文字列内のスラッシュ (/) 文字は、厳密には必要ない場合でも、円記号 (\) でエスケープできます。 これを利用して、ASP.NET AJAX チームは、代わりに文字列 "\/Date(ticks)\/" として DateTime インスタンスを記述するように JavaScriptSerializer を変更しました。 2 つのスラッシュのエスケープは表面的ですが、JavaScriptSerializer にとって重要です。 JSON ルールでは、"\/Date(ticks)\/" は技術的には /Date(ticks)/" と同等"ですが、JavaScriptSerializer は前者を DateTime として逆シリアル化し、後者を文字列として逆シリアル化します。 したがって、プレリリースのより単純な "@ticks@" 形式と比較すると、あいまいさの可能性はかなり低くなります。

特別な感謝

この記事を MSDN に提出する前に、多くのボランティアが記事を校正し、コンテンツ、文法、および方向性に関するフィードバックを提供していました。 レビュー プロセスの主な共同作成者には、グラスグラス・クロックフォード、Eric・シェールホルツァー、ミラノ・ネゴバンなどがあります。

作成者について

Atif Aziz は Skybow AG のプリンシパル コンサルタントであり、主な焦点は、顧客が .NET 開発プラットフォームでソリューションを理解し、構築するのを支援することです。 Atif は、カンファレンスで講演したり、技術資料の記事を作成したりすることで、Microsoft 開発者コミュニティに定期的に貢献しています。 彼は INETA スピーカーであり、最大のスイスの .NET ユーザー グループの社長です。 彼はで、または彼のウェブサイトhttp://www.raboof.comを介して到達atif.aziz@skybow.comすることができます .

Asp/ASP.NET の 6 冊の書籍の著者であり、4GuysFromRolla.com の創始者である Scott Mitchell は、1998 年から Microsoft Web テクノロジと協力しています。 Scott は、独立したコンサルタント、トレーナー、ライターとして働いています。 彼は彼のブログで mitchell@4guysfromrolla.com 、または彼のブログを介して到達することができます: http://ScottOnWriting.net.