jsonobject
jsonobject
ist eine PHP-Klasse zur Vereinfachung der Verwendung von Objekten, die aus einer JSON-Definition stammen. Die Idee entstand aus der Verwendung pydantic
in Python und seiner Fähigkeit, JSON-Daten in Objekte zu analysieren und zu validieren.
jsonobject
Ich musste eine API von PHP verwenden, und diese API gab mir jsonobject s zurück. Also musste ich sie in PHP-Objekte analysieren, die ich in der App verwenden konnte.
Der Arbeitsablauf ist
jsonobject
um die JSON-Definition zu analysierenNehmen wir das folgende JSON-Beispiel:
{
"id" : 0 ,
"name" : " John Doe " ,
"age" : 42 ,
"emails" : [
" [email protected] " ,
" [email protected] "
],
"address" : {
"street" : " My street " ,
"number" : 42 ,
"city" : " My city " ,
"country" : " My country "
}
}
Mit jsonobject
kann ich mein Datenmodell mithilfe der folgenden Klassen definieren:
class User extends jsonobject {
const ATTRIBUTES = [
' id ' => ' int ' ,
' name ' => ' str ' ,
' age ' => ' int ' ,
' emails ' => ' list[str] ' ,
' address? ' => ' Address ' ,
];
}
class Address extends jsonobject {
const ATTRIBUTES = [
' street ' => ' str ' ,
' number ' => ' int ' ,
' city ' => ' str ' ,
' country ' => ' str ' ,
];
}
Und fügen Sie dann den folgenden Befehl hinzu:
$ user = User:: fromObject ( json_decode ( $ json_text_definition ));
Die jsonobject
-Klasse führt die Analyse des Inhalts in Objekte durch, und wir könnten ihre Attribute wie definiert verwenden:
echo ( $ user -> name );
Die definierten Klassen können auch über Methoden verfügen, die die Implementierung des Datenmodells der Anwendung erleichtern. Beispielsweise wäre es möglich, die Klasse User
wie folgt zu definieren:
class User extends jsonobject {
const ATTRIBUTES = [
' id ' => ' int ' ,
' name ' => ' str ' ,
' age ' => ' int ' ,
' emails ' => ' list[str] ' ,
' address? ' => ' Address ' ,
];
public function isAdult () {
return $ this -> age >= 18 ;
}
}
jsonobject
Die Idee der jsonobject
-Klasse besteht darin, sie zum Parsen von JSON- Daten in Objekte zu verwenden. Damit diese Objekte andere Methoden enthalten können, die bei der Implementierung des Datenmodells der Anwendung helfen.
Wenn das JSON-Objekt (oder Array) analysiert wird, wird sein Inhalt rekursiv gemäß den in der ATTRIBUTES
Konstante definierten Typen analysiert. Wenn die Daten ungültig sind, weil sie nicht die erwarteten Werte enthalten, wird eine Ausnahme ausgelöst.
Um jsonobject zu verwenden, muss man jsonobject
in eine Unterklasse umwandeln und die Konstante ATTRIBUTES
für diese Klasse definieren, sodass sie die für die Objekte dieser Klasse erwarteten Attribute zusammen mit dem jeweiligen Typ definiert.
Die ATTRIBUTES
Konstante ist ein assoziatives Array, bei dem die Schlüssel der Name für jedes Attribut und die Werte der Typ für jedes Attribut sind.
Die möglichen Typen können sein:
jsonobject
sein muss. Beim Definieren des Namens der Attribute kann ein ?
am Ende des Namens, um anzuzeigen, dass das Attribut optional ist. Zum Beispiel der Attributname address?
im Abschnitt „Anwendungsfall“ ist optional.
Jedes Feld gilt als obligatorisch, sodass es im analysierten Objekt (oder Array) vorhanden sein muss. Darüber hinaus muss das Objekt vom definierten Typ sein (dh es muss vom spezifischen Typ korrekt analysiert werden).
Jedes Attribut, das nicht optional ist, gilt als obligatorisch. Dies ist in zwei Punkten von besonderem Interesse:
fromArray
oder fromObject
).jsonobject
Beim Erstellen des Objekts aus einer externen Struktur kümmert sich das jsonobject
um alle Pflichtfelder. Und wenn einer von ihnen fehlt, wird eine Ausnahme ausgelöst.
Im nächsten Beispiel wird eine Ausnahme ausgelöst, weil das obligatorische Feld „ Alter“ nicht angegeben ist.
class User extends jsonobject {
const ATTRIBUTES = [
" name " => " str " ,
" age " => " int " ,
];
}
( . . . )
$ user = User:: fromArray ([ " name " => " John " ]);
Beim Konvertieren des Objekts in ein Array oder in ein Objekt (oder beim Abrufen seiner JSON-Darstellung) erhält ein Pflichtfeld einen Standardwert, auch wenn dieser nicht festgelegt ist.
So im nächsten Beispiel
class User extends jsonobject {
const ATTRIBUTES = [
" name " => " str " ,
" age " => " int " ,
" birthDate? " => " str "
];
}
$ user = new User ();
echo (( string ) $ user );
Die Ausgabe wird sein
{
"name" : " " ,
"age" : 0
}
Denn während die Attribute „Name“ und „Alter“ obligatorisch sind und ihre Standardwerte erhalten (z. B. 0 für Zahlen, leer für Zeichenfolgen, Listen oder Diktate), ist das Attribut „ BirthDate“ nicht obligatorisch und wurde noch nicht festgelegt. Es wird also nicht in der Ausgabe generiert.
null
gesetztDas Problem, Werte auf Null zu setzen, ist von besonderer Bedeutung, wenn es darum geht, ob ein Attribut optional ist oder nicht.
Man könnte meinen, wenn wir einen Wert auf Null setzen, würde dies bedeuten, dass der Wert zurückgesetzt wird , und daher sollte dies nur für optionale Werte, nicht aber für obligatorische Werte möglich sein.
In jsonobject
haben wir ein anderes Konzept, denn das Setzen einer Eigenschaft auf null bedeutet „einen Wert auf null setzen“ und nicht das Deaktivieren der Eigenschaft. Um die Eigenschaft zu deaktivieren , sollten wir die Funktion unset oder ähnliches verwenden.
jsonobject
ermöglicht auch das Zurücksetzen von Werten. Bei einem optionalen Attribut bedeutet dies, dass der Wert entfernt wird und es daher keinen Wert in einer Array-Darstellung oder einem Objekt hat (wenn der Wert abgerufen wird, wird er auf null gesetzt).
Bei einem obligatorischen Attribut bedeutet die Deaktivierung jedoch, dass sein Wert auf den Standardwert zurückgesetzt wird . Das bedeutet, dass es mit dem Standardwert des Typs (z. B. 0 für Zahlen, leer für Listen, Zeichenfolgen oder Diktate usw.) oder seinem Standardwert in der ATTRIBUTES
Konstante initialisiert wird.
jsonobject
s können auch Attribute von ihren übergeordneten Klassen erben. Nehmen Sie das folgende Beispiel:
class Vehicle extends jsonobject {
const ATTRIBUTES = [
" brand " => " str " ,
" color " => " str "
]
}
class Car extends Vehicle {
const ATTRIBUTES = [
" wheels " => " int "
]
}
class Boat extends Vehicle {
const ATTRIBUTES = [
" length " => " float "
]
}
In diesem Beispiel verfügt die Klasse „ Vehicle
nur über die Attribute „Marke“ und „Farbe“ , die Klasse Car
hingegen über die Attribute „Marke“ , „Farbe“ und „Räder“ , während die Klasse „ Boat
über die Attribute „Marke“ , „Farbe“ und „Länge“ verfügt.
Objekte aus untergeordneten Klassen von jsonobject
können mit der statischen Methode ::fromArray
oder ::fromObject
erstellt werden, ausgehend von einem von JSON analysierten Objekt.
Im vorherigen Beispiel haben wir eine Datei car.json mit folgendem Inhalt:
{
"brand" : " BMW " ,
"color" : " black "
}
Wir können den folgenden Code verwenden, um eine Instanz der Vehicle
-Klasse abzurufen:
$ json = file_get_contents ( " car.json " );
$ vehicle = Vehicle:: fromArray (( array ) json_decode ( $ json , true ));
Eine Alternative besteht darin, Objekte wie im nächsten Beispiel zu instanziieren
* PHP 8 und höher:
$ car = new Car (brand: " BMW " , color: " black " , wheels: 4 );
* frühere PHP-Versionen:
$ car = new Car ([ " brand " => " BMW " , " color " => " black " , " wheels " => 4 ]);
jsonobject
Das jsonobject
ist die Kernklasse dieser Bibliothek. Seine Methoden sind:
__construct($data)
– Erstellt ein neues Objekt aus den angegebenen Daten__get($name)
– Gibt den Wert des Attributs mit dem angegebenen Namen zurück__set($name, $value)
– Legt den Wert für das Attribut mit dem angegebenen Namen fest__isset($name)
– Gibt true zurück, wenn das Attribut mit dem angegebenen Namen gesetzt ist__unset($name)
– Setzt den Wert eines optionalen Attributs zurück (oder setzt den Wert eines obligatorischen Attributs zurück).toArray()
– Gibt ein assoziatives Array mit den Daten des Objekts zurück. Das Array wird rekursiv erstellt, wobei jedes der Unterattribute für jedes Attribut aufgerufen wird.toObject()
– Gibt ein Objekt mit den Daten des Objekts als Attribute zurück. Das Array wird rekursiv erstellt, wobei jedes der Unterattribute für jedes Attribut aufgerufen wird.toJson()
– Gibt einen JSON-String mit der Darstellung des Objekts als Standardobjekt zurück.::fromArray($data)
– Erstellt ein Objekt, indem das angegebene assoziative Array in die in der Klasse definierten Attribute analysiert wird. Jedes der Attribute wird entsprechend dem für es definierten Typ rekursiv analysiert.::fromObject($data)
– Erstellt ein Objekt, indem das angegebene Objekt in die in der Klasse definierten Attribute analysiert wird. Jedes der Attribute wird entsprechend dem für es definierten Typ rekursiv analysiert. JsonDict
Dieses Objekt wird verwendet, um ein Wörterbuch zu verarbeiten, das aus einer JSON-Definition stammt. Die JsonDict
-Klasse ist so typisiert, dass jedes der Elemente von einem bestimmten Typ sein muss.
Die JsonDict
Objekte können als Array-ähnliche Objekte verwendet werden (z. B. $jsonDict["key1"]), aber (zum Zeitpunkt des Schreibens dieses Textes) wird der Typ der in das Wörterbuch eingefügten Elemente nicht überprüft. Der Typ wird zum Parsen des Inhalts beim Erstellen des Diktats verwendet (z. B. mit der statischen Funktion fromArray
) oder zum Speichern des Inhalts in einem Array oder einem Objekt (z. B. mit der Funktion toArray
).
Die Methoden sind:
toArray()
toObject()
::fromArray($data)
::fromObject($data)
Diese Methoden werden auf die gleiche Weise interpretiert wie im Fall von jsonobject
. Und der Typ der Elemente im Diktat kann sich auf komplexe Typen beziehen, die beim Parsen des Inhalts rekursiv berücksichtigt werden.
Beispielsweise wird der Typ list[list[int]]
verwendet, um [ [ 1, 2, 3], [ 4, 5, 6 ]]
zu analysieren.
JsonArray
Dieses Objekt ist weitgehend mit JsonDict
identisch, mit der Ausnahme, dass die Indizes ganze Zahlen sein müssen. In diesem Fall erzeugt $value["key1"]
eine Ausnahme.
In diesem Fall ist auch die Funktion zum Anhängen von Elementen an das Array (z. B. []
) implementiert.
Beim Definieren der Klasse ist es möglich, die Werte für die neu erstellten Objekte und für die optionalen Attribute zu initialisieren.
Es gibt zwei Möglichkeiten:
### Klasseneigenschaften verwenden
Es ist möglich, den Wert eines Objekts mithilfe der Klasseneigenschaften zu initialisieren. Wenn also der Wert für ein Attribut in der Klasse festgelegt ist, wird es als Attribut in die Instanz kopiert, sofern es definiert ist.
Z.B
class User extends jsonobject {
const ATTRIBUTES = [
' id ' => ' int ' ,
' name ' => ' str ' ,
' age ' => ' int ' ,
' emails ' => ' list[str] ' ,
' address? ' => ' Address ' ,
' sex? ' => ' str '
];
public $ sex = " not revealed " ;
}
Jetzt wird das Attribut sex
auf „nicht offenbart“ initialisiert, statt auf „null“ .
Die Vorgehensweise besteht darin, ein Tupel [ <type>, <default value> ]
für den Typ des Objekts zu definieren. Nehmen wir das nächste Beispiel:
class User extends jsonobject {
const ATTRIBUTES = [
' id ' => ' int ' ,
' name ' => ' str ' ,
' age ' => ' int ' ,
' emails ' => ' list[str] ' ,
' address? ' => ' Address ' ,
' sex? ' => [ ' str ' , ' not revealed ' ]
];
}
Das Attribut sex
ist beim Abrufen der Benutzerdaten optional. Wenn bei Verwendung dieser neuen Definition für die Klasse kein sex
festgelegt ist, wird der Wert auf „nicht offenbart“ anstelle von null
gesetzt.
Eine wichtige Funktion besteht darin, dass, wenn die als <Standardwert> festgelegte Zeichenfolge einer Methode des Objekts entspricht, diese beim Abrufen des Werts aufgerufen wird (sofern sie noch nicht festgelegt wurde) und der für diese Eigenschaft festgelegte Wert das Ergebnis des Anrufs sein.
Z.B
class User extends jsonobject {
const ATTRIBUTE = [
...
' birthDay? ' => [ ' str ' , ' computeBirthDate ' ]
]
function computeBirthDate () {
$ now = new DateTime ();
$ now ->sub( DateInterval ::createFromDateString("{ $ this -> age } years"));
return $ now ->format("Y-m-d");
}
}
Wenn wir in diesem Beispiel die birthDate
Eigenschaft nicht festgelegt haben, sie aber abgerufen wird, wird sie durch Subtrahieren des Alters vom aktuellen Datum berechnet.
Wenn Sie ein beliebiges Objekt in ein jsonobject
analysieren möchten, können Sie die Funktion jsonobject ::parse_typed_value
verwenden. Dies ist wichtig, um von jedem Typ in einen jsonobject
-Typ konvertieren zu können.
z.B
$ myobject = jsonobject :: parse_typed_value ( " list[str] " , [ " my " , " name " , " is " , " John " ]);
Erhält ein Objekt vom Typ JsonList<str>
.
Das Standardverhalten dieser Bibliothek besteht darin, sicherzustellen, dass die für die Attribute festgelegten Werte mit ihrem definierten Typ übereinstimmen. Das bedeutet aber, dass das Setzen eines Floats auf 0
fehlschlägt, da ein float
kein int
ist, da 0
eine ganze Zahl ist. In diesem Fall muss der Benutzer die Werte umwandeln, bevor er sie zuweist. Um zu steuern, ob der Typ so streng geprüft werden soll oder nicht, kann die Konstante STRICT_TYPE_CHECKING
verwendet werden.
Wenn
STRICT_TYPE_CHECKING
aufTrue
gesetzt ist, werden die Typen streng geprüft und z. B. die Zuweisung von9.3
zu einemint
löst eine Ausnahme aus. Wenn es aufFalse
gesetzt ist, werden die numerischen Typen von einem in den anderen konvertiert. Wenn wir also beispielsweise9.3
einemint
zuweisen, wird dieser automatisch auf9
gekürzt.
Eine weitere wichtige Typprüfung besteht darin, einem numerischen Typ einen leeren Wert (z. B. ""
oder null
) zuzuweisen. In diesem Fall haben wir die Konstante STRICT_TYPE_CHECKING_EMPTY_ZERO
.
Wenn
STRICT_TYPE_CHECKING_EMPTY_ZERO
aufTrue
gesetzt ist (das Standardverhalten), wird beim Zuweisen eines leeren Werts zu einem numerischen Typ dieser als0
betrachtet. Das heißt, die Zuweisung einer leeren Zeichenfolge oder einesnull
zu einemint
-Attribut bedeutet, dass0
zugewiesen wird. Wenn aufFalse
gesetzt, prüft die Bibliothek die Typen und löst schließlich eine Ausnahme aus.
Jetzt ermöglicht JsonList
auch die Verwendung negativer Indizes, sodass -1
das letzte Element, -2
das vorletzte usw. ist.
JsonList
Objekt enthält Funktionen zum Sortieren oder Filtern.
public function sort(callable $callback = null) : JsonList
: Sortiert die Liste anhand des angegebenen Rückrufs. Wenn kein Rückruf angegeben wird, wird die Liste mithilfe der Standardvergleichsfunktion sortiert.public function filter(callable $callback) : JsonList
: Filtert die Liste mithilfe des angegebenen Rückrufs. Der Rückruf muss einen booleschen Wert zurückgeben. Wenn der Rückruf true
zurückgibt, wird das Element in die resultierende Liste aufgenommen. Wenn es false
zurückgibt, wird das Element verworfen.