Zend_Json の高度な使用法

JSON オブジェクト

PHP オブジェクトを JSON にエンコードすると、 オブジェクトの public プロパティがすべて JSON オブジェクトにエンコードされます。

JSON はオブジェクトへの参照を扱うことができません。 再帰的な参照を伴うオブジェクトをエンコードしないように気をつけましょう。 再帰に関する問題が発生しないよう、 Zend_Json::encode() および Zend_Json_Encoder::encode() のオプションの二番目のパラメータで再帰をチェックできます。 オブジェクトが二度シリアライズされると、例外がスローされるようになります。

JSON オブジェクトのデコードは、さらに大変です。Javascript のオブジェクトを PHP に対応させるなら、連想配列にするのが一番近いでしょう。 しかし、中には「クラスの ID を渡してそのインスタンスを作成し、 JSON オブジェクトの キー/値 をそのインスタンスに代入すべきだという人もいます。 また、そんなことをするとセキュリティ上問題があるという人もいるでしょう。

デフォルトでは、Zend_JsonJSON オブジェクトを連想配列にデコードします。しかし、 もしオブジェクトとして受け取りたいのなら、そのように指定することもできます。

// JSONオブジェクトをPHPオブジェクトにデコードします
$phpNative = Zend_Json::decode($encodedValue, Zend_Json::TYPE_OBJECT);

このようにしてデコードされたオブジェクトは StdClass オブジェクトとなり、JSON の キー/値 のペアに対応するプロパティを保持します。

Zend Framework の推奨する方法は、各開発者が JSON オブジェクトのデコード方法を決めるべきだというものです。 もし特定の型のオブジェクトを返してほしいのなら、 お望みの型のオブジェクトを開発者自身が作成したうえで、 Zend_Json がデコードした値をそこに代入していけばいいのです。

PHP オブジェクトのエンコード

PHP オブジェクトをエンコードする際に、 デフォルトでエンコードメカニズムがアクセスできるのはオブジェクトの public プロパティのみです。エンコードするオブジェクトに toJson() メソッドが実装されていれば、 Zend_Json はこのメソッドを実行します。 このメソッドは、オブジェクトの内部状態を JSON 表現で返すものと期待されています。

内部エンコーダ/デコーダ

Zend_Json には二通りのモードがあり、PHP 環境で ext/json が有効になっているかどうかによってどちらを使うかが変わります。 ext/json がインストールされていれば、デフォルトで json_encode() 関数および json_decode() 関数を使用して JSON のエンコード/デコードを行います。 ext/json がインストールされていない場合は、PHP コードによる Zend Framework の実装を用いてエンコード/デコードを行います。 これは PHP 拡張モジュールを使う場合にくらべて相当遅くなりますが、 まったく同じ挙動になります。

しかし、ext/json がインストール環境で敢えて内部エンコーダ/ デコーダを使いたくなる場合もあるかもしれません。 そんなときは次のようにコールします。

Zend_Json::$useBuiltinEncoderDecoder = true:

JSON 式

Javascript では無名関数のコールバックを多用します。 そしてそれが JSON オブジェクト変数内に保存されます。 これが動作するのはダブルクォートの中で返されていない場合のみであり、 Zend_Json は当然そのようにします。 Zend_Json の式サポートを使用すれば、JSON オブジェクトを javascript コールバックとして正しい形式でエンコードできます。 これは、json_encode() と内部エンコーダの両方で動作します。

javascript コールバックは Zend_Json_Expr オブジェクトで表されます。 これは value object パターンを実装しており、不変 (immutable) です。 javascript の式を、コンストラクタの最初の引数として指定できます。 デフォルトでは Zend_Json::encode は javascript コールバックをエンコードしません。エンコードするには、 オプション enableJsonExprFinder を渡し、 encode 関数に TRUE を設定しなければなりません。 これを有効にすると、 大きなオブジェクト構造の中の入れ子状の式に対しても式サポートが有効となります。 次のようにして使用します。

$data = array(
    'onClick' => new Zend_Json_Expr('function() {'
              . 'alert("I am a valid javascript callback '
              . 'created by Zend_Json"); }'),
    'other' => 'no expression',
);
$jsonObjectWithExpression = Zend_Json::encode(
    $data,
    false,
    array('enableJsonExprFinder' => true)
);