<?xml version="1.0" encoding="UTF-8"?>
<!-- Reviewed: no -->
<!-- EN-Revision: 15103 -->
<sect1 id="zend.json.advanced">
    <title>Zend_Json の高度な使用法</title>

    <sect2 id="zend.json.advanced.objects1">
        <title>JSON オブジェクト</title>
        <para>
            PHP オブジェクトを JSON にエンコードすると、
            オブジェクトの public プロパティがすべて JSON
            オブジェクトにエンコードされます。
        </para>
        <para>
            JSON はオブジェクトへの参照を扱うことができません。
            再帰的な参照を伴うオブジェクトをエンコードしないように気をつけましょう。
            再帰に関する問題が発生しないよう、
            <classname>Zend_Json::encode()</classname> および
            <classname>Zend_Json_Encoder::encode()</classname>
            のオプションの二番目のパラメータで再帰をチェックすることができます。
            オブジェクトが二度シリアライズされると、例外がスローされるようになります。
        </para>
        <para>
            JSON オブジェクトのデコードは、さらに大変です。Javascript
            のオブジェクトを PHP に対応させるなら、連想配列にするのが一番近いでしょう。
            しかし、中には「クラスの ID を渡してそのインスタンスを作成し、
            JSON オブジェクトの キー/値 をそのインスタンスに代入すべきだという人もいます。
            また、そんなことをするとセキュリティ上問題があるという人もいるでしょう。
        </para>
        <para>
            デフォルトでは、<classname>Zend_Json</classname> は JSON
            オブジェクトを連想配列にデコードします。しかし、
            もしオブジェクトとして受け取りたいのなら、そのように指定することもできます。
        </para>
        <programlisting role="php"><![CDATA[
// JSONオブジェクトをPHPオブジェクトにデコードします
$phpNative = Zend_Json::decode($encodedValue, Zend_Json::TYPE_OBJECT);
]]>
        </programlisting>
        <para>
            このようにしてデコードされたオブジェクトは <code>StdClass</code>
            オブジェクトとなり、JSON の キー/値
            のペアに対応するプロパティを保持します。
        </para>
        <para>
            Zend Framework の推奨する方法は、各開発者が JSON
            オブジェクトのデコード方法を決めるべきだというものです。
            もし特定の型のオブジェクトを返してほしいのなら、
            お望みの型のオブジェクトを開発者自身が作成したうえで、
            <classname>Zend_Json</classname> がデコードした値をそこに代入していけばいいのです。
        </para>
    </sect2>

    <sect2 id="zend.json.advanced.objects2">
        <title>PHP オブジェクトのエンコード</title>

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

    <sect2 id="zend.json.advanced.internal">
        <title>内部エンコーダ/デコーダ</title>

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

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

        <programlisting role="php"><![CDATA[
Zend_Json::$useBuiltinEncoderDecoder = true:
]]>
        </programlisting>
    </sect2>

    <sect2 id="zend.json.advanced.expr">
        <title>JSON 式</title>

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

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

        <programlisting role="php"><![CDATA[
$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)
);
]]>
        </programlisting>
    </sect2>
</sect1>
<!--
vim:se ts=4 sw=4 et:
-->
