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

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

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

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

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

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

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

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

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

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

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

        <programlisting language="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:
-->
