次の方法で共有


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

 

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

Atif Aziz、Scott Mitchell

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 について説明し、JSON メッセージの作成と解析の例を JavaScript と C# で提供しています。

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

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

  
    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 ガイド 」の 「Literals」セクションを参照してください

JavaScript リテラルから JSON へ

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

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

JSON の痛みのポイントの 1 つは、日付/時刻リテラルが不足している点です。 多くの人々は、最初にJSONに遭遇したときにこれを学ぶことに驚き、がっかりしています。 日付/時刻リテラルがない場合の簡単な説明 (慰めるか否か) は、JavaScript にどちらも含まれていないということです。JavaScript での日付と時刻の値のサポートは、 完全に Date オブジェクトを通じて提供されます。 JSON をデータ形式として使用するほとんどのアプリケーションでは、通常、日付と時刻の値を表すために文字列または数値を使用する傾向があります。 文字列を使用する場合、通常は ISO 8601 形式であることが期待できます。 代わりに数値を使用する場合、通常、エポックは 1970 年 1 月 1 日午前 0 時 (UTC) として定義されるエポック以降のユニバーサル協定時刻 (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 があります。 ASP.NET AJAX の一部としての初期実装を除き、現時点では何もありません。
プラットフォームと言語 パーサーとフォーマッタは、多くのプラットフォームと言語 (商用およびオープンソース実装) で広く利用できます。 パーサーとフォーマッタは、多くのプラットフォームと多くの言語で既に使用できます。 参照 適切なセットについては、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 型に 対してJSONString() 関数が追加されます。 スカラー型 (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 を呼び出そうとすると、解析された結果として undefined が返されます。 かっこを使用すると、JavaScript パーサーは、ステートメント ブロックを定義する中かっこではなく、Object インスタンスのリテラル表記として最上位の中かっこを強制的に表示します。 なお、最上位項目が配列の場合、 eval("[1,2,3]") のように同じ問題は発生しません。 ただし、統一性のために、JSON テキストは eval を呼び出す前に常にかっこで囲んで、ソースの解釈方法にあいまいさがないようにする必要があります。

リテラル表記を評価する場合、リテラル構文に対応するインスタンスが返され、 value に割り当てられます。 次の例では、 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 には ASP.NET AJAX という名前の独自 の Ajax ライブラリもあります。

この記事では、共同編集者 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 クラス XmlWriter、XmlReaderXmlTextWriter、および XmlTextReader のセマンティクスを模倣します。 これらのクラスは、低およびストリーム指向レベルの JSON とのインターフェイスに役立ちます。 これらのクラスを使用すると、一連のメソッド呼び出しを通じて JSON テキストを作成または解析できます。 たとえば、 JsonWriter クラス メソッド WriteNumber(number) を使用すると、JSON 標準に従って 数値 の適切な文字列表現が書き込まれます。 JsonConvert クラスには、.NET 型と JSON の間で変換するための Export メソッドと Import メソッドが用意されています。 これらのメソッドは、 XmlSerializer クラス メソッドの Serialize および Serialize で見られるのと同様の機能を提供します。

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 行のコメントはスラッシュ (//) で始まり、複数行のコメントはスラッシュstar (/*) で、末尾は star スラッシュ (*/) です。 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).gifBb299886.intro_to_json02

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

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

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

まとめ

JSON は、JavaScript プログラミング言語のリテラル表記のサブセットに基づく、軽量のテキストベースのデータ交換形式です。 アプリケーション データ構造に簡潔なエンコードを提供し、通常、Ajax スタイルの Web アプリケーションなど、データを交換するアプリケーションの一方または両方で JavaScript 実装を使用できるシナリオで使用されます。 JSON の魅力は、理解、導入、実装が簡単であることにあります。 JSON には、豊富なリテラル表記 (Python や Ruby など) に対する同様のサポートを備えた JavaScript やその他のプログラミング言語に既に精通している開発者にとって、学習曲線はほとんどありません。 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 という用語は、非同期 JavaScript と XML を意味する頭字語 AJAX として Web の周りに広がっていました。 しかし、時間の経過と共に、ほとんどの実装がよりシンプルで効率的な代替手段として JSON に切り替えられたため、AJAX の "X" は、バックグラウンドで Web サーバーとの通信に使用される基になるデータ形式をあまり表していないことに気付きました。 したがって、AJAJのような少し舌のツイスターのような代わりの頭字語を思い付くのではなく、頭字語は一般的にAJAXの頭字語ではなくAjaxの用語を支持して廃止されています。

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

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

ASP.NET の AJAX JSON シリアライザーは 、DateTime インスタンスを JSON 文字列としてエンコードします。 リリース前のサイクルで、ASP.NET AJAX では "@ticks@" という形式が使用されました。ここで、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 として逆シリアル化し、後者を String として逆シリアル化します。 したがって、プレリリースのより単純な "@ticks@" 形式と比較すると、あいまいさの可能性はかなり低くなります。

特別な感謝

この記事を MSDN に送信する前に、多くのボランティアが記事の文章校正に役立ち、コンテンツ、文法、および指示に関するフィードバックを提供していました。 レビュー プロセスの主な貢献者には、ダグラス・クロックフォード、エリック・シェーンホルツァー、ミラノ・ネゴヴァンなどがあります。

作成者について

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

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