Ajax (Asynchronous JavaScript + XML) の出現によって、Web アプリケーション開発に新たな意気込みが生まれ、多くのアーキテクトと開発者が Web アプリケーションの作成方法を見直すようになりました。JSON (JavaScript Object Notation) とは、ブラウザー上で実行するビジネス・ロジックでデータを表現するためのデータ交換形式の 1 つで、この JSON を使用してブラウザー側の JavaScript コードでデータを直接処理する方法は多くの Ajax 開発者に選ばれています。JSON が普及するにつれ、エンタープライズ・アプリケーション・データを XML 形式ではなく JSON 形式でブラウザーに提供するミドルウェア・サーバー・プログラムもますます必要になってくるはずです。これはつまり、開発者が XML でエンコードされた既存のサーバー側エンタープライズ・データを JSON に変換してからブラウザーに送信しなければならないことを意味します。この記事では、PHP ベースのサーバー・プログラムを使用して、XML 形式のアプリケーション・データを JSON 形式に変換してからブラウザー・アプリケーションに送信する方法を紹介します。
XML はマークアップの定義に関する標準です。XML ベースのマークアップを使用して記述されるデータはタグによって表現されますが、このタグは事前定義する必要がありません。このように必要に応じて新しいタグを考案できるので、XML は極めて拡張性に優れています。リスト 1 は、XML で表現したデータ構造の一例です。
リスト 1. 単純な XML データの例
<?xml version="1.0" encoding="UTF-8"?>
<contacts>
<contact id="1">
<name>John Doe</name>
<phone>123-456-7890</phone>
<address>
<street>123 JFKStreet</street>
<city>Any Town</city>
<state>Any State</state>
<zipCode>12345</zipCode>
</address>
</contact>
</contacts>
|
先頭行は、使用する XML バージョンと文字エンコード方式を指定する XML 宣言です。これに続くルート要素 <contacts> は、複数の子要素を囲んでいます。この子要素のネスト構造がまとまって、連絡先のデータを定義します。注目すべき点は、<address> 要素に含まれる子要素が <contact> 要素のサブツリー構造になっていることです。また、XML では開始タグに属性を持たせ、要素に関する追加情報を提供することもできます。上記では、<contact> 要素に含まれる属性によって id 属性が割り当てられています。XML 文書は、ルート要素に対応する終了タグ </contacts> で完了します。
JSON は XML のようなマークアップ言語ではなく、テキスト・ベースのデータ交換形式であり、JavaScript のオブジェクトと配列のデータ構文です。つまり、JSON を使うとデータを簡潔に表現できます。例えば、オブジェクトは中括弧 ({}) で囲み、配列は大括弧 ([]) で囲むなどです。JavaScript コードは、特別な構文解析や追加でデータ変換を行うことなく、JSON でエンコードされたデータをそのまま使用することができます。リスト 2 は、JSON 形式で表現したデータ構造です。
リスト 2. 単純な JSON データの例
{
"contacts" : {
"contact" : {
"@attributes" : {
"id" : "1"
},
"name" : "John Doe",
"phone" : "123-456-7890",
"address" : {
"street" : "123 JFK Street",
"city" : "Any Town",
"state" : "Any State",
"zipCode" : "12345"
}
}
}
}
|
リスト 2 の JSON の例には、リスト 1 の XML の例に示されたデータの各部分が示されていますが、その違いは、JSON が JavaScript オブジェクトおよび配列のデータ型を使用してデータをエンコードする方法です。データ構造は "contacts" という名前のプロパティーが含まれるオブジェクトで始まっていますが、このプロパティー自体がオブジェクトで、この "contacts" オブジェクトに含まれる "contact" というプロパティーも同じくオブジェクトです。"contact" オブジェクトに含まれる複数のプロパティーが、連絡先の詳細を構成しています。"contact" オブジェクトには、アドレスの詳細を記述する "address" という別の (ネストされた) オブジェクトが含まれていることに注意してください。XML の場合と同じく JSON 形式のデータも自己記述型なので、人間も機械も容易に読み取ることができます。
それでは、ブラウザー側のコードではデータがどのように処理されるかを見てみましょう。サーバーがブラウザーに XML データを送信すると、XML データは DOM (Document Object Model) API によって処理されます。ただし JavaScript 開発者がこのデータで何らかの操作を行うためには、XML の複雑な処理内容をすべて理解し、XML データを構文解析するための追加コードを大量に作成しなければなりません。ところが JSON の出現により、ブラウザーの要求に応答して JSON でエンコードしたアプリケーション・データをサーバー側のコードがパッケージ化して送ることが可能になりました。サーバー側のコードが JSON 形式のデータをブラウザーに送信すれば、JavaScript 開発者が追加の複雑なロジックを作成して XML を構文解析する必要はなくなります。さらに、JSON 形式で受信したデータは、ブラウザー側のコードでそのまま JavaScript 固有のデータ構造として処理されることになります。リスト 3 のコード・スニペットを見ると、JSON 形式のデータを処理するための追加作業は一切必要ないことがわかります。
リスト 3. サーバーから受信した JSON 形式のデータを処理するコード・スニペット
var result = httpRequest.responseText;
jsonResponse = eval('(' + result + ')');
|
リスト 3 のブラウザー側のコード・スニペットでは、result はサーバーから受信した JSON 形式のストリングを示します。必要なのは、JSON 形式のストリングを eval ステートメントで評価することによって、ストリング・データをネイティブ JavaScript データ型に変換する 1 行だけです。これを見れば、ブラウザー側で JSON データを処理するのは遥かに簡単であることがわかるはずです。JSON を使用することで、ブラウザー側のコードが簡潔で価値あるものになります。
リスト 3 の eval ステートメントは、サーバーが戻すあらゆるコードを実行するので、セキュリティー上のリスクが伴いますが、ブラウザーのセキュリティー・ポリシーにより、JavaScript の HTTP 要求はコードのロード元サーバーに制限されるためリスクは限られています。それでも状況によっては、eval ステートメントに渡す前に、正規表現などによってサーバーから受信したデータが期待したものと同じであることを検証するのが賢明な場合もあります。
XML データから JSON への変換が必要なアプリケーションが増えるなか、このような変換を行う Web ベースのサービスがすでにいくつか登場しています。IBM T.J. Watson Research Center では、PHP を使用して変換する特定の手法を開発しました。この手法は、XML ストリング・データを入力として受け入れ、JSON 形式のデータ出力に変換します。この PHP ベースのソリューションには、以下の利点があります。
- コマンド・ラインから実行して、スタンドアロン・モードで動作させることができます。
- 既存のサーバー側コード成果物に組み込むことができます。
- Web 上の Web サービスとして簡単にホストできます。
XML から JSON への変換には、以下のコアとなる PHP 機能が必要となります。
- SimpleXMLElement
- http://pear.php.net の Services_JSON (詳細は「参考文献」を参照)
SimpleXMLElement は、PHP バージョン 5 以降でサポートされます。これは、XML 文書内のデータが含まれるプロパティーを持つオブジェクトです。Services_JSON は 2005年の終わり近くに承認された PHP オープン・ソースの提案で、JSON 固有のエンコーダー (PHP データから JSON へのエンコード) 関数とデコーダー (JSON から PHP データへのデコード) 関数を提供します。このオープン・ソースの PHP クラス・ライブラリーは現在、PEAR Web サイトから入手できます (「参考文献」を参照)。
上記の 2 つのコアとなる PHP 機能を使用することで、あらゆる XML データを JSON に変換することが可能になります。まず必要なのは、SimpleXMLElement を使って XML コンテンツを適切な PHP データ型に変換することです。この PHP データを Services_JSON エンコーダーに提供すれば、最終的な JSON 形式の出力になります。
この xml2json 実装は、以下の 3 つの部分で構成されています。
- xml2json.php - 2 つの静的関数を持つ PHP クラス
- xml2json_test.php - xml2json 変換関数を実行するテスト・ドライバー
- test1.xml、test2.xml、test3.xml、test4.xml - 複雑度の異なる XML ファイル
簡潔にするため、この記事ではコードに詳細のコメントを含めていませんが、付属のソース・ファイルのコードには完全なコメントが記載されています。プログラム・ロジックの完全な詳細については、付属のソース・ファイルを参照してください (「ダウンロード」を参照)。
リスト 4 では、いくつかの便利な定数を定義しています。コードの先頭行が Services_JSON 実装をインポートします。
リスト 4. xml2json.php での定数の定義
require_once 'json/JSON.php';
// Internal program-specific Debug option.
define ("DEBUG", false);
// Maximum Recursion Depth that we can allow.
define ("MAX_RECURSION_DEPTH_ALLOWED", 25);
// An empty string
define ("EMPTY_STR", ");
// SimpleXMLElement object property name for attributes
define ("SIMPLE_XML_ELEMENT_OBJECT_PROPERTY_FOR_ATTRIBUTES", "@attributes");
// SimpleXMLElement object name.
define ("SIMPLE_XML_ELEMENT_PHP_CLASS", "SimpleXMLElement");
|
リスト 5 に示すコード・スニペットは、xml2json コンバーターへの入力関数です。この関数は XML データを入力として使用し、XML ストリングを SimpleXMLElement オブジェクトに変換します。SimpleXMLElement オブジェクトはこのクラスの別の (再帰的) 関数に入力として送信され、その関数によって XML 要素が PHP 連想配列に変換されます。変換された配列は次に入力として Services_JSON エンコーダーに渡され、このエンコーダーが JSON 形式の出力を提供します。
リスト 5. xml2json.php での Services_JSON の使用
public static function transformXmlStringToJson($xmlStringContents) {
$simpleXmlElementObject = simplexml_load_string($xmlStringContents);
|
リスト 6 に示す長いコード・スニペットは、PHP オープン・ソース・コミュニティー (「参考文献」を参照) から発想を得た再帰手法を使用して、SimpleXMLElement オブジェクトを入力として受け入れ、ネストされた XML ツリーで再帰的ツリー・ウォークを行っています。アクセスしたすべての XML 要素は PHP 連想配列に格納されます。再帰の深さの制限は、リスト 4 で定義した定数を変更することで調整できます。
リスト 6. xml2json.php での変換ロジック
public static function convertSimpleXmlElementObjectIntoArray($simpleXmlElementObject,
&$recursionDepth=0) {
// Keep an eye on how deeply we are involved in recursion.
|
XML ツリー・ウォークが完了すると、この関数は PHP 連想配列に含まれるすべての XML 要素 (ルート要素およびすべての子要素) を変換して格納します。複雑な XML 文書の場合は、PHP 配列も同じく複雑になります。PHP 配列が完全に構成されると、あとは Services_JSON エンコーダーで簡単にこの配列を JSON 形式のデータに変換することができます。この再帰ロジックを理解するには、文書化されたソース・ファイルを調べてください。
リスト 7 のコード・スニペットは、xml2json コンバーターのロジックを実行するテスト・ドライバーです。
リスト 7. xml2json_test.php
<?php
require_once("xml2json.php");
|
このプログラムをコマンド・ラインから実行するには、コマンド・ラインの引数として XML ファイル名を使用します。
php -f xml2json_test.php test2.xml |
コマンド・ラインから実行すると、プログラムはファイルの XML コンテンツをストリング変数に読み込みます。次に xml2json クラスの静的関数を呼び出し、JSON 形式の結果を取得します。このプログラムはコマンド・ラインから実行できるだけでなく、このソース・ファイルのロジックを変更すれば、xml2json コンバーターを SOAP (Simple Object Access Protocol) または REST (Representational State Transfer) アクセス・プロトコルによるリモート呼び出しが可能な Web サービスとして公開することもできます。このような変更が必要な場合、PHP では最小限の作業で簡単に変更できます。
リスト 8 に示すのは、この記事付属の xml2json 実装をテストするための 4 つのテスト XML ファイルのうちの 1 つです。複雑度はテスト・ファイルによって異なります。コマンド・ラインの引数として、これらのファイルのいずれかをテスト・ドライバー xml2json_test.php に渡すことができます。
リスト 8. test2.xml による xml2json 実装のテスト
<?xml version="1.0" encoding="UTF-8"?>
<books>
<book id="1">
<title>Code Generation in Action</title>
<author><first>Jack</first><last>Herrington</last></author>
<publisher>Manning</publisher>
</book>
|
リスト 9 のコード・スニペットは、test2.xml をテスト・ドライバー xml2json_test.php へのコマンド・ラインの引数として使用した場合の JSON 形式の結果です。
リスト 9. test2.xml を使用した場合の JSON 形式の結果
{
"books" : {
"book" : [ {
"@attributes" : {
"id" : "1"
},
"title" : "Code Generation in Action",
"author" : {
"first" : "Jack", "last" : "Herrington"
},
"publisher" : "Manning"
}, {
"@attributes" : {
"id" : "2"
},
"title" : "PHP Hacks", "author" : {
"first" : "Jack", "last" : "Herrington"
},
"publisher" : "O'Reilly"
}, {
"@attributes" : {
"id" : "3"
},
"title" : "Podcasting Hacks", "author" : {
"first" : "Jack", "last" : "Herrington"
},
"publisher" : "O'Reilly"
}
]}
}
|
JSON データでは、<book> 要素の XML 属性 ID は、"@attributes" オブジェクト・プロパティーとして格納され、<book> 要素はオブジェクトの配列として格納されることに注目してください。この JSON 出力は、eval ステートメントを使って JavaScript コード内でそのまま使用できます。
Web 開発者たちの間では、JSON の勢いに弾みがつき始めたばかりにすぎません。主に JavaScript 開発者の間で見られる JSON の成功は、その簡潔さと単純さによるものです。JSON は、状況によっては XML に値する代替手段となります。この記事では、ミドルウェア・サーバー層での XML から JSON への変換の必要性を要約し、XML でエンコードされた既存のエンタープライズ・データを JSON 形式のデータとして活用することで、ブラウザー側のプログラムがデータを簡単に利用できるようになるという論理的根拠を強調しました。さらに、XML から JSON への変換を実際に実行できる PHP コードも提供しています (「ダウンロード」を参照)。
この記事に記載したソース・コードは、さまざまな方法で使用できます。例えば、スタンドアロン・ツールとして使用することも、共有クラス・ライブラリーとして既存のサーバー側プログラムで使用することも、あるいは SOAP/REST Web サービス機能として使用してエンタープライズ SOA (サービス指向アーキテクチャー) に参加することもできます。
| 内容 | ファイル名 | サイズ | ダウンロード形式 |
|---|---|---|---|
| PHP code for xml2json | x-xml2json_php.zip | 14KB | HTTP |
学ぶために
- 「Mastering Ajax, Part 1: Introduction to Ajax」(Brett McLaughlin 著、developerWorks、2005年12月): Ajax の詳細を学んでください。
- 「JSON を使ったキャッシング」(Bakul L. Patel 著、developerWorks、2006年11月): サーバー・コードを利用してクライアント側でメタデータをキャッシュし、メタデータを JSON 形式のストリングにする方法を説明しています。
- 「Ajax と REST、第 1 回」(Bill Higgins 著、 developerWorks、2006年10月): 没入型 Web アプリケーションでの Ajax/REST アーキテクチャー・スタイルの利点について説明しています。
- 「PHPでダイナミックに」(Jack Herrington 著、developerWorks、2006年2月): PHP V5 の動的機能を使用する方法を説明しています。
- 「Developing PHP the Ajax way, Part 1: Getting started」(Sean Kelly 著、developerWorks、2006年5月): PHP と Ajax を使用する際の導入編となります。
- IBM developerWorks Ajax resource center: Ajax に関する記事とチュートリアルが揃っています。
- IBM developerWorks XML ゾーン: XML に関するすべての情報はここで探してください。
- IBM developerWorks SOA and web services ゾーン: SOA および Web サービスの詳細を学んでください。
- 導入JSON: JSON (JavaScript Object Notation) の情報源です。
- PHP オープン・ソース・コミュニティー: PHP に関するあらゆる情報を調べてください。
- PHP Manual: 23 ヶ国語で用意された極めて役に立つ PHP 資料です。
- XML 技術文書一覧: 広範な技術に関する記事とヒント、チュートリアル、標準、そして IBM レッドブックについては、developerWorks XML ゾーンを参照してください。
- developerWorks technical events and webcasts: これらのセッションで最新情報を入手してください。
製品や技術を入手するために
- PEAR (PHP Extension and Application Repository) Web サイト: Services_JSON ライブラリーをダウンロードしてください。
- IBM ソフトウェア評価版: developerWorks から直接ダウンロードできるトライアル・ソフトウェアで、次の開発プロジェクトを構築してください。
議論するために
- developerWorks ブログ: developerWorks コミュニティーに参加してください。

Senthil Nathan は、ニューヨーク州 Hawthorne にある IBM T.J. Watson Research Center のシニア・ソフトウェア・エンジニアです。 22 年間、各種エンタープライズ・アプリケーションを対象としたソフトウェアの作成に取り組んできました。現在専門としているのは、一連の話題の技術、SOA、Web サービス、Java 2 Platform、J2EE (Enterprise Edition)、PHP、Ruby On Rails、Web 2.0、そして Ajax の開発です。

