完全なPHPオブジェクトグラフをJSON文字列表現にシリアル化し、シリアル化を解除して同じPHPオブジェクトグラフに戻したいと思いました。
これが私が検討したオプションの要約と、それらが私のために機能しない理由です:
serialize()
PHPに固有の形式を使用しているため、私が望むことを実行しません。ほとんどの言語で広くサポートされており、人間が読める形式/編集可能な形式が必要です。json_encode()
オブジェクトではなく、単純な値と配列のみを実行するため、私が望むことは実行しません。(私は実際にこれを私の実装で使用しています。以下を参照してください。)var_export()
循環参照を処理せず、私が望むことを実行しません(上記を参照)(私の現在の実装も循環参照を処理しないことに注意してください-この問題の明確化については、以下のコメントと返信を参照してください)。SebastianBergmannのObjectFreezerは優れた実装ですが、私が望むことも実行しません。非常に長い形式を使用し、シリアル化されたオブジェクトにGUIDを詰め込むことに依存しています。
Serializedは、私が望むことを実行しません。実際にはシリアル化を実行せず
serialize()
、XMLなどの別の表現を解析して生成しますが、その表現を解析することはできません。(JSONもサポートしていません-XMLは非常に長い形式であり、私が望むものではありません。)
私は今、共有するための実用的な実装を持っています:
https://github.com/mindplay-dk/jsonfreeze
オブジェクトグラフのJSON表現は次のようになります。
{
"#type": "Order",
"orderNo": 123,
"lines": [{
"#type": "OrderLine",
"item": "milk \"fuzz\"",
"amount": 3,
"options": null
}, {
"#type": "OrderLine",
"item": "cookies",
"amount": 7,
"options": {
"#type": "#hash",
"flavor": "chocolate",
"weight": "1\/2 lb"
}
}],
"paid": true
}
このアプローチは、純粋なツリー構造の集合体に対して機能するように設計されています。循環参照は許可されておらず、同じオブジェクトへの複数の参照も許可されていません。言い換えれば、これはegのような汎用ではなくserialize()
、unserialize()
PHPオブジェクトグラフに対して機能します。
私の最初のアプローチでは、基本的にオブジェクトのベース0リストであるシリアル化されたフォームを使用しました。リストの最初のオブジェクト(番号0)は、シリアル化されたオブジェクトグラフのルートです。他のオブジェクトは、見つかった順序で格納されます。
現在の実装では、JSON表現は、これが可能な範囲で元のツリー構造に似ており、JavaScriptでオブジェクトグラフのJSON表現を実際に操作できるようになっています。唯一の違いは、マジック#type
プロパティ(プロパティ名との衝突を防ぐために#が前に付けられます)と、タイプハッシュ(JSONオブジェクトとして保存)と通常のタイプ配列(JSON配列として保存)#hash
を区別するために使用される「タイプ」です。array
array
以前のバージョンに関するこれらのメモは、歴史的な目的のためにここに残しておきます。
循環参照は、ネストされたオブジェクトを各オブジェクトのシリアル化された表現内に格納しないことによって単純に処理されます-代わりに、オブジェクト参照は、object-indexを持つJSONオブジェクトとして格納されます-たとえば、オブジェクトにインデックスを{"__oref":2}
持つオブジェクトへの参照です-2
リスト。
実装で配列参照に問題があります-オブジェクトへの参照を配列に復元するコード内でvar_dump()を実行すると、それらは入力されますが、ある時点で配列がコピーされ、最終的には空のコピー。&
コード内のいたるところに文字を配置しようとしましたが、参照で渡す場所に関係なく、最終結果は空の配列になります。