Ich mag Ihre Vorschläge, nur um zu bemerken, dass es nicht mit verschachtelten Objekten (außer STDClass oder dem konvertierten Objekt)
funktioniert
33
Wir haben JsonMapper erstellt , um JSON-Objekte automatisch unseren eigenen Modellklassen zuzuordnen . Es funktioniert gut mit verschachtelten / untergeordneten Objekten.
Für die Zuordnung werden nur Informationen zum Docblock-Typ verwendet, die die meisten Klasseneigenschaften ohnehin haben:
Können Sie die OSL3-Lizenz erklären? Muss ich den Quellcode dieser Website freigeben, wenn ich JsonMapper auf einer Website verwende? Wenn ich JsonMapper in Code auf einem von mir verkauften Gerät verwende, muss der gesamte Code dieses Geräts Open Source sein?
EricP
Nein, Sie müssen nur die Änderungen veröffentlichen, die Sie an JsonMapper selbst vornehmen.
Cweiske
29
Sie können es tun - es ist ein Kludge, aber absolut möglich. Wir mussten tun, als wir anfingen, Dinge auf der Couchbase zu lagern.
$stdobj = json_decode($json_encoded_myClassInstance);//JSON to stdClass
$temp = serialize($stdobj);//stdClass to serialized// Now we reach in and change the class of the serialized object
$temp = preg_replace('@^O:8:"stdClass":@','O:7:"MyClass":',$temp);// Unserialize and walk away like nothing happend
$myClassInstance = unserialize($temp);// Presto a php Class
In unseren Benchmarks war dies viel schneller als der Versuch, alle Klassenvariablen zu durchlaufen.
Vorsichtsmaßnahme: Funktioniert nicht für andere verschachtelte Objekte als stdClass
Bearbeiten: Beachten Sie die Datenquelle. Es wird dringend empfohlen, dies nicht mit nicht vertrauenswürdigen Daten von Benutzern zu tun, ohne die Risiken sehr sorgfältig zu analysieren.
Funktioniert dies mit gekapselten Unterklassen? ZB { "a": {"b":"c"} }, wo das Objekt in aeiner anderen Klasse ist und nicht nur ein assoziatives Array?
J-Rou
2
nein, json_decode erstellt stdclass-Objekte, einschließlich Unterobjekte. Wenn Sie möchten, dass sie etwas anderes sind, müssen Sie jedes Objekt wie oben beschrieben kludgen.
John Pettitt
Danke, das habe ich mir vorgestellt
J-Rou
Wie wäre es mit der Verwendung dieser Lösung für Objekte, für die der Konstruktor Parameter hat? Ich kann es nicht zum Laufen bringen. Ich hatte gehofft, jemand könnte mich in die richtige Richtung weisen, damit diese Lösung mit einem Objekt funktioniert, das einen benutzerdefinierten Konstruktor mit Parametern hat.
Die Syntax ist nicht abhängig von der JMS Serializer-Version, sondern von der PHP-Version - ab PHP5.5 können Sie die ::classNotation verwenden: php.net/manual/en/…
Ivan Yarych
4
Sie können einen Wrapper für Ihr Objekt erstellen und den Wrapper so aussehen lassen, als wäre er das Objekt selbst. Und es funktioniert mit mehrstufigen Objekten.
<?php
classObj{public $slave;publicfunction __get($key){return property_exists ( $this->slave , $key )? $this->slave->{$key}:null;}publicfunction __construct(stdClass $slave){
$this->slave = $slave;}}
$std = json_decode('{"s3":{"s2":{"s1":777}}}');
$o =newObj($std);
echo $o->s3->s2->s1;// you will have 777
Wie Gordon sagt, ist das nicht möglich. Wenn Sie jedoch nach einer Möglichkeit suchen, eine Zeichenfolge zu erhalten, die als Instanz einer give-Klasse dekodiert werden kann, können Sie stattdessen serialize und unserialize verwenden.
Dies scheint die Frage nicht zu beantworten. Wenn dies der Fall ist, müssen Sie eine Erklärung abgeben.
Felix Kling
1
Zu diesem Zweck habe ich einmal eine abstrakte Basisklasse erstellt. Nennen wir es JsonConvertible. Es sollte die öffentlichen Mitglieder serialisieren und deserialisieren. Dies ist durch Reflexion und späte statische Bindung möglich.
Nur aus dem Gedächtnis, also wahrscheinlich nicht fehlerfrei. Sie müssen auch statische Eigenschaften ausschließen und können abgeleiteten Klassen die Möglichkeit geben, einige Eigenschaften bei der Serialisierung zu / von json zu ignorieren. Ich hoffe, Sie haben trotzdem die Idee.
JSON ist ein einfaches Protokoll zum Übertragen von Daten zwischen verschiedenen Programmiersprachen (und es ist auch eine Teilmenge von JavaScript), das nur bestimmte Typen unterstützt: Zahlen, Zeichenfolgen, Arrays / Listen, Objekte / Dikte. Objekte sind nur Schlüssel = Wert-Maps und Arrays sind geordnete Listen.
Es gibt also keine Möglichkeit, benutzerdefinierte Objekte generisch auszudrücken. Die Lösung besteht darin, eine Struktur zu definieren, in der Ihre Programme wissen, dass es sich um ein benutzerdefiniertes Objekt handelt.
Hier ist ein Beispiel:
{"cls":"MyClass", fields:{"a":123,"foo":"bar"}}
Dies könnte verwendet werden, um eine Instanz von zu erstellen MyClassund die Felder aund fooauf 123und zu setzen "bar".
Dies mag zutreffen, aber es geht nicht darum, Objekte generisch darzustellen. Es hört sich so an, als hätte er eine bestimmte JSON-Tasche, die an einem oder beiden Enden einer bestimmten Klasse zugeordnet ist. Es gibt keinen Grund, warum Sie JSON auf diese Weise nicht als explizite Serialisierung nicht generischer benannter Klassen verwenden können. Es ist in Ordnung, es so zu benennen, wie Sie es tun, wenn Sie eine generische Lösung wünschen, aber es ist auch nichts Falsches daran, einen vereinbarten Vertrag über die JSON-Struktur zu haben.
DougW
Dies könnte funktionieren, wenn Sie Serializable auf der Codierungsseite implementieren und Bedingungen auf der Decodierungsseite haben. Könnte sogar mit Unterklassen arbeiten, wenn sie richtig organisiert sind.
Dies funktionierte perfekt für meinen Anwendungsfall. Die Antwort von Jewgenij Afanasjew erscheint mir jedoch ebenso vielversprechend. Es könnte möglich sein, dass Ihre Klasse einen zusätzlichen "Konstruktor" hat, wie folgt:
publicstaticfunction withJson(string $json){
$instance =newstatic();// Do your thingreturn $instance;}
useApp\Model\Person;
$person =newPerson();
$person->setName('foo');
$person->setAge(99);
$person->setSportsperson(false);
$jsonContent = $serializer->serialize($person,'json');// $jsonContent contains {"name":"foo","age":99,"sportsperson":false,"createdAt":null}
echo $jsonContent;// or return it in a Response
Deserialisierung von JSON zu Object: (In diesem Beispiel wird XML verwendet, um die Flexibilität von Formaten zu demonstrieren.)
Antworten:
Nicht automatisch. Aber Sie können es auf der altmodischen Route tun.
Alternativ können Sie dies auch automatischer gestalten:
Edit : etwas schicker werden:
quelle
Wir haben JsonMapper erstellt , um JSON-Objekte automatisch unseren eigenen Modellklassen zuzuordnen . Es funktioniert gut mit verschachtelten / untergeordneten Objekten.
Für die Zuordnung werden nur Informationen zum Docblock-Typ verwendet, die die meisten Klasseneigenschaften ohnehin haben:
quelle
Sie können es tun - es ist ein Kludge, aber absolut möglich. Wir mussten tun, als wir anfingen, Dinge auf der Couchbase zu lagern.
In unseren Benchmarks war dies viel schneller als der Versuch, alle Klassenvariablen zu durchlaufen.
Vorsichtsmaßnahme: Funktioniert nicht für andere verschachtelte Objekte als stdClass
Bearbeiten: Beachten Sie die Datenquelle. Es wird dringend empfohlen, dies nicht mit nicht vertrauenswürdigen Daten von Benutzern zu tun, ohne die Risiken sehr sorgfältig zu analysieren.
quelle
{ "a": {"b":"c"} }
, wo das Objekt ina
einer anderen Klasse ist und nicht nur ein assoziatives Array?Sie können die Serializer-Bibliothek von J ohannes Schmitt verwenden .
In der neuesten Version des JMS-Serializers lautet die Syntax:
quelle
::class
Notation verwenden: php.net/manual/en/…Sie können einen Wrapper für Ihr Objekt erstellen und den Wrapper so aussehen lassen, als wäre er das Objekt selbst. Und es funktioniert mit mehrstufigen Objekten.
quelle
Nein, dies ist ab PHP 5.5.1 nicht möglich.
Das einzige, was möglich ist, ist,
json_decode
assoziierte Arrays anstelle der StdClass-Objekte zurückzugeben.quelle
Sie können es auf folgende Weise tun ..
?>
Weitere Informationen finden Sie unter create-custom-class-in-php-from-json-or-array
quelle
Wie Gordon sagt, ist das nicht möglich. Wenn Sie jedoch nach einer Möglichkeit suchen, eine Zeichenfolge zu erhalten, die als Instanz einer give-Klasse dekodiert werden kann, können Sie stattdessen serialize und unserialize verwenden.
quelle
Zu diesem Zweck habe ich einmal eine abstrakte Basisklasse erstellt. Nennen wir es JsonConvertible. Es sollte die öffentlichen Mitglieder serialisieren und deserialisieren. Dies ist durch Reflexion und späte statische Bindung möglich.
Nur aus dem Gedächtnis, also wahrscheinlich nicht fehlerfrei. Sie müssen auch statische Eigenschaften ausschließen und können abgeleiteten Klassen die Möglichkeit geben, einige Eigenschaften bei der Serialisierung zu / von json zu ignorieren. Ich hoffe, Sie haben trotzdem die Idee.
quelle
Verwenden Reflexion :
quelle
JSON ist ein einfaches Protokoll zum Übertragen von Daten zwischen verschiedenen Programmiersprachen (und es ist auch eine Teilmenge von JavaScript), das nur bestimmte Typen unterstützt: Zahlen, Zeichenfolgen, Arrays / Listen, Objekte / Dikte. Objekte sind nur Schlüssel = Wert-Maps und Arrays sind geordnete Listen.
Es gibt also keine Möglichkeit, benutzerdefinierte Objekte generisch auszudrücken. Die Lösung besteht darin, eine Struktur zu definieren, in der Ihre Programme wissen, dass es sich um ein benutzerdefiniertes Objekt handelt.
Hier ist ein Beispiel:
Dies könnte verwendet werden, um eine Instanz von zu erstellen
MyClass
und die Feldera
undfoo
auf123
und zu setzen"bar"
.quelle
Ich ging voran und implementierte John Petits Antwort als Funktion ( Kern ):
Dies funktionierte perfekt für meinen Anwendungsfall. Die Antwort von Jewgenij Afanasjew erscheint mir jedoch ebenso vielversprechend. Es könnte möglich sein, dass Ihre Klasse einen zusätzlichen "Konstruktor" hat, wie folgt:
Dies ist auch von dieser Antwort inspiriert .
quelle
Ich bin überrascht, dass dies noch niemand erwähnt hat.
Verwenden Sie die Symfony Serializer-Komponente: https://symfony.com/doc/current/components/serializer.html
Serialisierung von Objekt zu JSON:
Deserialisierung von JSON zu Object: (In diesem Beispiel wird XML verwendet, um die Flexibilität von Formaten zu demonstrieren.)
quelle
Ich denke, der einfachste Weg ist:
quelle