7

完全な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を区別するために使用される「タイプ」です。arrayarray


以前のバージョンに関するこれらのメモは、歴史的な目的のためにここに残しておきます。

循環参照は、ネストされたオブジェクトを各オブジェクトのシリアル化された表現内に格納しないことによって単純に処理されます-代わりに、オブジェクト参照は、object-indexを持つJSONオブジェクトとして格納されます-たとえば、オブジェクトにインデックスを{"__oref":2}持つオブジェクトへの参照です-2リスト。

実装で配列参照に問題があります-オブジェクトへの参照を配列に復元するコード内でvar_dump()を実行すると、それらは入力されますが、ある時点で配列がコピーされ、最終的には空のコピー。&コード内のいたるところに文字を配置しようとしましたが、参照で渡す場所に関係なく、最終結果は空の配列になります。

4

2 に答える 2

1

完成したスクリプト(上記に投稿)は、私の正確な要件を満たしています。

  • アグリゲート全体をシリアル化および非シリアル化します。

  • 元のデータ構造によく似たJSON表現を用意します。

  • 動的に生成されたキーやその他のデータでデータ構造を汚染しないでください。

循環参照は処理しません。上記のコメントで指摘されているように、同じオブジェクトへの循環参照または複数の参照を格納する正しい方法はありません。これらはすべて等しいためです。これに気づき、オブジェクトグラフは通常のツリーである必要があると判断し、この制限を「良いこと」として受け入れました。

更新:出力をインデント、改行、空白でフォーマットできるようになりました。目的のために、人間が読み取れる(そしてソース管理に適した)表現を持つことが重要でした。(フォーマットは必要に応じて有効または無効にできます。)

于 2012-06-07T01:42:29.370 に答える
0

これがあなたが求めているものであるかどうかはわかりませんが、オブジェクトのパブリックプロパティを取得することにのみ関心がある場合は、get_object_vars($ obj)でうまくいきます。

<?php

class foo {
    public $fname = "John";
    public $sname = "Doe";
    private $status = null;
    static $type = "person";


}

$obj = new foo;

print_r( (get_object_vars($obj)) );

print json_encode(get_object_vars($obj));

?>

出力します:

配列([fname] => John [sname] => Doe)

{"fname": "John"、 "sname": "Doe"}

上記の方法は、関数参照やプライベート変数にアクセスするのには役に立ちませんが、これをさらにいくつかのコードと組み合わせて使用​​して、必要なものをノックアップできる場合があります。

ディネッシュ。

于 2012-05-31T15:12:14.697 に答える