Als ich über die neue JsonSerializable-Schnittstelle stolperte, suchte ich in php.net nach Informationen zum Serialisieren von PHP-Objekten in JSON . Es ist jedoch nur PHP> = 5.4 und ich arbeite in einer 5.3.x-Umgebung.
Wie wird diese Art von Funktionalität erreicht PHP <5.4 ?
Ich habe noch nicht viel mit JSON gearbeitet, aber ich versuche, eine API-Schicht in einer Anwendung zu unterstützen, und das Dumping des Datenobjekts ( das sonst an die Ansicht gesendet würde) in JSON wäre perfekt.
Wenn ich versuche, das Objekt direkt zu serialisieren, wird eine leere JSON-Zeichenfolge zurückgegeben. Das liegt daran, dass ich vermutlich json_encode()
nicht weiß, was zum Teufel mit dem Objekt zu tun ist. Sollte ich das Objekt in ein Array rekursiv reduzieren, und dann codieren , dass ?
Beispiel
$data = new Mf_Data();
$data->foo->bar['hello'] = 'world';
echo json_encode($data)
erzeugt ein leeres Objekt:
{}
var_dump($data)
funktioniert jedoch wie erwartet:
object(Mf_Data)#1 (5) {
["_values":"Mf_Data":private]=>
array(0) {
}
["_children":"Mf_Data":private]=>
array(1) {
[0]=>
array(1) {
["foo"]=>
object(Mf_Data)#2 (5) {
["_values":"Mf_Data":private]=>
array(0) {
}
["_children":"Mf_Data":private]=>
array(1) {
[0]=>
array(1) {
["bar"]=>
object(Mf_Data)#3 (5) {
["_values":"Mf_Data":private]=>
array(1) {
[0]=>
array(1) {
["hello"]=>
string(5) "world"
}
}
["_children":"Mf_Data":private]=>
array(0) {
}
["_parent":"Mf_Data":private]=>
*RECURSION*
["_key":"Mf_Data":private]=>
string(3) "bar"
["_index":"Mf_Data":private]=>
int(0)
}
}
}
["_parent":"Mf_Data":private]=>
*RECURSION*
["_key":"Mf_Data":private]=>
string(3) "foo"
["_index":"Mf_Data":private]=>
int(0)
}
}
}
["_parent":"Mf_Data":private]=>
NULL
["_key":"Mf_Data":private]=>
NULL
["_index":"Mf_Data":private]=>
int(0)
}
Nachtrag
1)
Das ist also die toArray()
Funktion, die ich für die Mf_Data
Klasse entwickelt habe:
public function toArray()
{
$array = (array) $this;
array_walk_recursive($array, function (&$property) {
if ($property instanceof Mf_Data) {
$property = $property->toArray();
}
});
return $array;
}
Da die Mf_Data
Objekte jedoch auch einen Verweis auf ihr übergeordnetes ( enthaltendes ) Objekt haben, schlägt dies mit der Rekursion fehl. Funktioniert jedoch wie ein Zauber, wenn ich die _parent
Referenz entferne .
2)
Die letzte Funktion zum Transformieren eines komplexen Baumknotenobjekts, mit dem ich mich befasst habe, war:
// class name - Mf_Data
// exlcuded properties - $_parent, $_index
public function toArray()
{
$array = get_object_vars($this);
unset($array['_parent'], $array['_index']);
array_walk_recursive($array, function (&$property) {
if (is_object($property) && method_exists($property, 'toArray')) {
$property = $property->toArray();
}
});
return $array;
}
3)
Ich folge wieder mit einer etwas saubereren Implementierung. Die Verwendung von Schnittstellen für eine instanceof
Überprüfung scheint viel sauberer zu sein als method_exists()
( jedoch method_exists()
übergreifende Vererbung / Implementierung ).
Die Verwendung unset()
schien auch etwas chaotisch zu sein, und es scheint, dass die Logik in eine andere Methode umgestaltet werden sollte. Allerdings ist diese Implementierung hat die Eigenschaft Array (Kopie wegenarray_diff_key
), so etwas zu prüfen.
interface ToMapInterface
{
function toMap();
function getToMapProperties();
}
class Node implements ToMapInterface
{
private $index;
private $parent;
private $values = array();
public function toMap()
{
$array = $this->getToMapProperties();
array_walk_recursive($array, function (&$value) {
if ($value instanceof ToMapInterface) {
$value = $value->toMap();
}
});
return $array;
}
public function getToMapProperties()
{
return array_diff_key(get_object_vars($this), array_flip(array(
'index', 'parent'
)));
}
}
quelle
JsonSerializable
Antworten:
Bearbeiten : Es ist derzeit 24.09.2016 und PHP 5.4 wurde am 01.03.2012 veröffentlicht und der Support wurde am 01.09.2015 beendet . Dennoch scheint diese Antwort positive Stimmen zu erhalten. Wenn Sie immer noch PHP <5.4 verwenden, schaffen Sie ein Sicherheitsrisiko und gefährden Ihr Projekt . Wenn Sie keine zwingenden Gründe haben, bei <5.4 zu bleiben oder sogar bereits Version> = 5.4 zu verwenden, verwenden Sie diese Antwort nicht und verwenden Sie einfach PHP> = 5.4 (oder, wie Sie wissen, eine neuere) und implementieren Sie die JsonSerializable-Schnittstelle
Sie würden eine Funktion definieren, zum Beispiel einen Namen
getJsonData();
, die entweder ein Array, einstdClass
Objekt oder ein anderes Objekt mit sichtbaren Parametern anstelle von privaten / geschützten zurückgibt, und ajson_encode($data->getJsonData());
. Implementieren Sie die Funktion im Wesentlichen ab 5.4, rufen Sie sie jedoch von Hand auf.So etwas würde funktionieren, wie
get_object_vars()
es innerhalb der Klasse aufgerufen wird, und Zugriff auf private / geschützte Variablen haben:quelle
stdClass
? Ich denke in Richtung Reflexion , aber wenn nicht, werde ich einfach etwas herausfinden, um es rekursiv auszuführen.getJsonData()
, können Sieget_object_vars()
dieses Ergebnis einfach aufrufen und durchlaufen, um nach weiteren Objekten zu suchen._parent
Eigenschaft, sodass der Baum zur Wurzel durchlaufen werden kann. Siehe meine Bearbeitung für ein Update; Vielleicht sollte ich eine andere Frage stellen, da diese Ausgabe jetzt von meinem Original abstrahiert ist.unset($array['_parent']);
vor dem Spaziergang sollte den Trick machen.$parent
als Benutzerdaten an übergebenarray_walk_recursive()
. Einfach ist schön! Es liegt auch an$array["\0class\0property"]
der Null-Byte-Verschmutzung, weil ich Casting verwendet habe. Ich denke, ich werde zu wechselnget_object_vars()
.In den einfachsten Fällen sollte ein Tipp funktionieren:
quelle
json_encode()
codiert nur öffentliche Mitgliedsvariablen. Wenn Sie also das Private einbeziehen möchten, müssen Sie es selbst tun (wie von den anderen vorgeschlagen).quelle
Der folgende Code erledigt die Arbeit mit Reflektion. Es wird davon ausgegangen, dass Sie Getter für die Eigenschaften haben, die Sie serialisieren möchten
quelle
Implementieren Sie einfach eine von PHP JsonSerializable bereitgestellte Schnittstelle .
quelle
Da Ihr Objekttyp benutzerdefiniert ist, stimme ich Ihrer Lösung eher zu - zerlegen Sie sie mithilfe einer Codierungsmethode (wie JSON oder Serialisierung des Inhalts) in kleinere Segmente und verfügen Sie am anderen Ende über entsprechenden Code, um das Objekt neu zu erstellen.
quelle
Meine Version:
Implementierung:
JsonUtils: GitHub
quelle
Versuchen Sie es damit, das hat bei mir gut funktioniert.
quelle
Wechseln Sie zu Ihren Variablentypen
private
zupublic
Dies ist einfach und besser lesbar.
Beispielsweise
Funktioniert nicht;
Es funktioniert;
quelle
Ich habe eine nette Hilfsklasse erstellt, die ein Objekt mit get-Methoden in ein Array konvertiert. Es beruht nicht auf Eigenschaften, sondern nur auf Methoden.
Ich habe also das folgende Überprüfungsobjekt, das zwei Methoden enthält:
Rezension
Kommentar
Das Skript, das ich geschrieben habe, verwandelt es in ein Array mit Eigenschaften, die wie folgt aussehen:
Quelle: PHP Serializer, der ein Objekt in ein Array konvertiert, das in JSON codiert werden kann.
Alles was Sie tun müssen, ist json_encode um die Ausgabe zu wickeln.
Einige Informationen zum Skript:
quelle
Ich habe einige Stunden mit dem gleichen Problem verbracht. Mein zu konvertierendes Objekt enthält viele andere, deren Definitionen ich nicht berühren soll (API). Daher habe ich eine Lösung gefunden, die möglicherweise langsam ist, aber ich verwende sie für Entwicklungszwecke.
Dieser konvertiert jedes Objekt in ein Array
Dadurch wird jedes Objekt in stdClass konvertiert
quelle
unlink($thisAnswer);