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'
)));
}
}
JsonSerializable