Ich wollte einen kompletten PHP-Objektgraphen in eine JSON-Zeichenfolgen-Repräsentation serialisieren und ihn wieder in einen identischen PHP-Objektgraphen deserialisieren.
Hier finden Sie eine Zusammenfassung der von mir in Betracht gezogenen Optionen und Gründe, warum sie für mich nicht funktionieren:
-
serialize()
tut nicht, was ich möchte, da es ein PHP-spezifisches Format verwendet. Ich möchte ein Format, das von den meisten Sprachen weitgehend unterstützt wird und menschenlesbar/editierbar ist. -
json_encode()
tut nicht, was ich möchte, weil es nur einfache Werte und Arrays, nicht jedoch Objekte unterstützt. (Ich verwende dies tatsächlich in meiner Implementierung, siehe unten.) -
var_export()
behandelt keine zirkulären Referenzen und tut nicht, was ich möchte (siehe oben). (Beachten Sie, dass meine aktuelle Implementierung auch keine zirkulären Referenzen behandelt - siehe Kommentare und Antworten unten zur Klärung dieses Problems.) -
Sebastian Bergmanns Object Freezer ist eine gute Implementierung, erfüllt jedoch nicht meine Anforderungen - er verwendet eine sehr lange Form und verlässt sich darauf, die serialisierten Objekte mit GUIDs zu füllen.
-
Serialized tut nicht, was ich möchte - es führt keine tatsächliche Serialisierung durch, sondern analysiert die Ausgabe von
serialize()
und erstellt eine andere Repräsentation, z. B. XML, kann aber diese Repräsentation nicht wieder analysieren. (es unterstützt auch kein JSON - XML ist sehr lang und entspricht nicht meinen Anforderungen.)
Ich habe jetzt eine funktionierende Implementierung zum Teilen:
https://github.com/mindplay-dk/jsonfreeze
Die JSON-Repräsentation des Objektgraphen sieht so aus:
{
"#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
}
Dieser Ansatz ist darauf ausgelegt, für eine reine Baumstruktur-Aggregation zu funktionieren - zirkuläre Referenzen sind nicht erlaubt, ebenso wenig wie mehrfache Verweise auf dieselben Objekte. Mit anderen Worten, dies ist nicht wie z. B. serialize()
und unserialize()
für beliebige PHP-Objektgraphen geeignet.
In meinem ursprünglichen Ansatz verwendete ich eine serialisierte Form, die im Wesentlichen eine Basis-0-Liste von Objekten war. Das erste Objekt in der Liste (Nummer 0) ist die Wurzel des serialisierten Objektgraphen, alle anderen Objekte werden in der Reihenfolge gespeichert, in der sie gefunden wurden.
In der aktuellen Implementierung ähnelt die JSON-Repräsentation der Originalbaumstruktur soweit dies möglich ist, was es ermöglicht, tatsächlich mit der JSON-Repräsentation eines Objektgraphen in JavaScript zu arbeiten. Die einzige Abweichung ist das magische #type
Eigenschaft (mit # versehen, um Kollisionen mit Eigenschaftsnamen zu verhindern) und der #hash
"Typ", der verwendet wird, um array
-Typ-Hashes (gespeichert als JSON-Objekte) von regulären array
-Typ-Arrays (gespeichert als JSON-Arrays) zu unterscheiden.
Ich lasse diese Notizen zur früheren Version hier aus historischen Gründen stehen.
Zirkuläre Verweise werden einfach behandelt, indem niemals verschachtelte Objekte innerhalb der serialisierten Repräsentation jedes Objekts gespeichert werden - stattdessen wird jeder Objektverweis als JSON-Objekt mit dem Objektindex gespeichert - z. B. {"__oref":2}
ist ein Verweis auf das Objekt mit dem Index 2
in der Objektliste.
Ich habe ein Problem mit Array-Verweisen in meiner Implementierung - wenn ich ein var_dump() im Code platziere, der Verweise auf Objekte im Array wiederherstellt, werden sie gefüllt, aber irgendwann wird das Array kopiert und am Ende erhalten Sie die leere Kopie. Ich habe versucht, überall im Code &
Zeichen zu platzieren, aber unabhängig davon, wo ich die Referenz weitergebe, ist das Endergebnis ein leeres Array.