Übernimmt von einem JSON-Webdienst abgerufene Daten und wandelt sie in verschachtelte Objekte und Arrays um – unter Verwendung Ihrer eigenen Modellklassen.
Ausgehend von einem Basisobjekt ordnet es JSON-Daten Klasseneigenschaften zu und konvertiert sie in die richtigen einfachen Typen oder Objekte.
Es ist ein bisschen wie die native SOAP-Parameterzuordnung, die PHPs SoapClient Ihnen bietet, aber für JSON. Es basiert nicht auf einem Schema, sondern nur auf Ihren PHP-Klassendefinitionen.
Die Typerkennung erfolgt durch das Parsen von Typdeklarationen und @var Docblock-Anmerkungen von Klasseneigenschaften sowie von Typhinweisen in Setter-Methoden.
Sie müssen Ihre Modellklassen nicht durch Hinzufügen von JSON-spezifischem Code ändern; Es funktioniert automatisch, indem es bereits vorhandene Dokumentblöcke analysiert.
Diese Bibliothek hat keine Abhängigkeiten.
Schlüsselwörter: Deserialisierung, Hydratation
Inhalt
map()Modellklassen müssen von Hand geschrieben werden
Da JsonMapper nicht auf Schemainformationen (z. B. von json-schema) angewiesen ist, können Modellklassen nicht automatisch generiert werden.
netresearch/jsonmapper mit ComposerJsonMapper Objektinstanzmap oder mapArray aufOrdnen Sie ein normales Objekt zu:
<?php
require ' autoload.php ' ;
$ mapper = new JsonMapper ();
$ contactObject = $ mapper -> map ( $ jsonContact , new Contact ());
// or as classname
$ contactObject = $ mapper -> map ( $ jsonContact , Contact::class);Ordnen Sie ein Array von Objekten zu:
<?php
require ' autoload.php ' ;
$ mapper = new JsonMapper ();
$ contactsArray = $ mapper -> mapArray (
$ jsonContacts , array (), ' Contact '
); Anstelle von array() können Sie auch ArrayObject und abgeleitete Klassen sowie Klassen verwenden, ArrayAccess implementieren.
JSON von einem Adressbuch-Webdienst:
{
"name" : "Sheldon Cooper" ,
"address" : {
"street" : "2311 N. Los Robles Avenue" ,
"city" : "Pasadena"
}
} Ihre lokale Contact :
<?php
class Contact
{
/**
* Full name
*/
public string $ name ;
public ? Address $ address ;
} Ihre lokale Address :
<?php
class Address
{
public $ street ;
public $ city ;
public function getGeoCoords ()
{
//do something with $street and $city
}
}Ihr Anwendungscode:
<?php
$ json = json_decode ( file_get_contents ( ' http://example.org/sheldon.json ' ));
$ mapper = new JsonMapper ();
$ contact = $ mapper -> map ( $ json , new Contact ());
echo " Geo coordinates for " . $ contact -> name . " : "
. var_export ( $ contact -> address -> getGeoCoords (), true ); JsonMapper verwendet mehrere Quellen, um den richtigen Typ einer Eigenschaft in der folgenden Reihenfolge zu erkennen:
Setter-Methode ( set + ucwords($propertyname) )
Unterstriche „ _ “ und Bindestriche „ - “ machen den nächsten Buchstaben groß. Die Eigenschaft foo_bar-baz führt zur Setter-Methode setFooBarBaz .
Wenn die Methodensignatur einen Typhinweis enthält, wird folgender Typ verwendet:
öffentliche Funktion setPerson(Contact $person) {...}
Der Dokumentblock der Methode wird auf @param $type -Anmerkungen überprüft:
/**
* @param Kontakt $person Hauptkontakt für diese Anwendung
*/
öffentliche Funktion setPerson($person) {...}
Wenn kein Typ erkannt werden konnte, wird der einfache JSON-Wert an die Setter-Methode übergeben.
Klasseneigenschaftstypen (seit PHP 7.4):
öffentlicher Kontakt $person;
Typen der Konstruktor-Eigenschaftsförderung (seit PHP 8.0):
öffentliche Funktion __construct(protected Contact $person) {}
@var $type docblock Annotation von Klasseneigenschaften:
/** * @var myapplicationmodelContact */ öffentliche $person;
Für eine unmittelbare Nutzung muss das Grundstück öffentlich sein. Sie können $bIgnoreVisibility auch verwenden, um geschützte und private Eigenschaften zu nutzen.
Wenn kein Typ erkannt werden konnte, erhält die Eigenschaft den einfachen JSON-Wertsatz.
Wenn eine Eigenschaft nicht gefunden werden kann, versucht JsonMapper, die Eigenschaft ohne Berücksichtigung der Groß-/Kleinschreibung zu finden. Eine JSON-Eigenschaft isempty würde dann einer PHP-Eigenschaft isEmpty zugeordnet.
Notiz
Damit der Typ funktioniert, müssen Sie den vollständig qualifizierten Namespace bereitstellen. Relative Klassennamen werden im Kontext des aktuellen Klassen-Namensraums ausgewertet, wobei eventuell vorhandene Importe NICHT berücksichtigt werden.
PHP stellt die Importe nicht über Reflection bereit; Der Kommentartext enthält nur den Literaltext des Typs. Aus Leistungsgründen analysiert JsonMapper den Quellcode nicht selbst, um etwaige Importe zu erkennen und zu erweitern.
Einfache Typen
stringbool , booleanint , integerdouble , floatarrayobjectmixedKlassennamen, mit und ohne Namespaces
Contact – Eine Ausnahme wird ausgelöst, wenn der JSON-Wert null istArrays einfacher Typen und Klassennamen:
int[]Contact[]Mehrdimensionale Arrays:
int[][]TreeDeePixel[][][]ArrayObjects einfacher Typen und Klassennamen:
ContactList[Contact]NumberList[int]Unterstützte Aufzählungen mit und ohne Namespaces
Suit:string|Suit:int– Ausnahme wird ausgelöst, wenn der JSON-Wert nicht in der Aufzählung vorhanden ist
Nullable-Typen:
int|null oder ?int – ist null , wenn der Wert in JSON null ist, andernfalls ist es eine GanzzahlContact|null oder ?Contact – ist null , wenn der Wert in JSON null ist, andernfalls handelt es sich um ein Objekt vom Typ ContactArrayObjects und Erweiterungsklassen werden als Arrays behandelt.
Variablen ohne Typ oder mit mixed Typ erhalten den JSON-Wert direkt und ohne Konvertierung.
Weitere Informationen finden Sie in der Typdokumentation von phpdoc.
Notiz
Diese Funktion ist aus Sicherheitsgründen seit Version 5 standardmäßig deaktiviert. Weitere Informationen finden Sie unter $bStrictObjectTypeChecking.
Wenn ein Objekt erstellt werden soll, der JSON jedoch nur einen einfachen Typ enthält (z. B. String, Float, Boolean), wird dieser Wert an den Konstruktor der Klassen übergeben. Beispiel:
PHP-Code:
public DateTime $ date ;JSON:
{ "date" : "2014-05-15" } Dies führt dazu, dass new DateTime('2014-05-15') aufgerufen wird.
Wenn Variablen als Objekte abstrakter Klassen oder Schnittstellen definiert werden, versucht JsonMapper normalerweise, diese direkt zu instanziieren, was zum Absturz führt.
Mit der Eigenschaft $classMap von JsonMapper können Sie angeben, welche Klassen stattdessen instanziiert werden sollen:
$ jm = new JsonMapper ();
$ jm -> classMap [ ' Foo ' ] = ' Bar ' ;
$ jm -> map (...); Dadurch würden Objekte vom Typ Bar erstellt, wenn eine Variable als Typ Foo definiert ist.
Es ist auch möglich, ein Callable zu verwenden, wenn die tatsächliche Implementierungsklasse dynamisch bestimmt werden muss (z. B. im Fall einer Union). Die zugeordnete Klasse (im Beispiel unten „Foo“) und die Json-Daten werden als Parameter an den Aufruf übergeben.
$ mapper = function ( $ class , $ jvalue ) {
// examine $class and $jvalue to figure out what class to use...
return ' DateTime ' ;
};
$ jm = new JsonMapper ();
$ jm -> classMap [ ' Foo ' ] = $ mapper ;
$ jm -> map (...); JsonMapper löst eine Ausnahme aus, wenn eine JSON-Eigenschaft null ist, es sei denn, die PHP-Klasseneigenschaft hat einen nullfähigen Typ – z. B. Contact|null oder ?Contact .
Wenn Ihre API viele Felder enthält, die möglicherweise null sind, und Sie nicht alle Ihre Typdefinitionen auf NULL setzen möchten, legen Sie Folgendes fest:
$ jm -> bStrictNullTypes = false ; Seit Version 5.0.0 führen null in Arrays zu einer JsonMapper_Exception es sei denn, der Typ ist nullbar – z. B. array[?string] oder array[string|null] .
Um das vorherige Verhalten wiederherzustellen (Nullwerte sind auch dann zulässig, wenn dies nicht deklariert ist), legen Sie Folgendes fest:
$ jm -> bStrictNullTypesInArrays = false ; setLogger() Methode von JsonMapper unterstützt alle PSR-3-kompatiblen Logger-Instanzen.
Ereignisse, die protokolliert werden:
Während der Entwicklung ändern sich APIs häufig. Um über solche Änderungen benachrichtigt zu werden, kann JsonMapper so konfiguriert werden, dass bei fehlenden oder noch unbekannten Daten Ausnahmen ausgelöst werden.
Wenn JsonMapper Eigenschaften in den JSON-Daten erkennt, die nicht in der PHP-Klasse definiert sind, können Sie eine Ausnahme auslösen lassen, indem Sie $bExceptionOnUndefinedProperty festlegen:
$ jm = new JsonMapper ();
$ jm -> bExceptionOnUndefinedProperty = true ;
$ jm -> map (...); Sie können diese Eigenschaften auch selbst verwalten, indem Sie einen Callable auf $undefinedPropertyHandler setzen:
/**
* Handle undefined properties during JsonMapper::map()
*
* @param object $object Object that is being filled
* @param string $propName Name of the unknown JSON property
* @param mixed $jsonValue JSON value of the property
*
* @return void
*/
function setUndefinedProperty ( $ object , $ propName , $ jsonValue )
{
$ object ->{ ' UNDEF ' . $ propName } = $ jsonValue ;
}
$ jm = new JsonMapper ();
$ jm -> undefinedPropertyHandler = ' setUndefinedProperty ' ;
$ jm -> map (...); Oder wenn Sie JsonMapper den Setter für Sie übernehmen lassen möchten, können Sie eine Zeichenfolge vom $undefinedPropertyHandler zurückgeben, die als Eigenschaftsname verwendet wird.
/**
* Handle undefined properties during JsonMapper::map()
*
* @param object $object Object that is being filled
* @param string $propName Name of the unknown JSON property
* @param mixed $jsonValue JSON value of the property
*
* @return void
*/
function fixPropName ( $ object , $ propName , $ jsonValue )
{
return ucfirst ( $ propName );
}
$ jm = new JsonMapper ();
$ jm -> undefinedPropertyHandler = ' fixPropName ' ;
$ jm -> map (...);Notiz
Dies funktioniert nur, wenn $bStrictObjectTypeChecking aktiviert bleibt.
Eigenschaften in Ihren PHP-Klassen können als „erforderlich“ markiert werden, indem Sie @required in ihren Dokumentblock einfügen:
/**
* @var string
* @required
*/
public $ someDatum ; Wenn die JSON-Daten diese Eigenschaft nicht enthalten, löst JsonMapper eine JsonMapper_Exception aus, wenn $bExceptionOnMissingData aktiviert ist:
$ jm = new JsonMapper ();
$ jm -> bExceptionOnMissingData = true ;
$ jm -> map (...); Die Option $bRemoveUndefinedAttributes bewirkt, dass JsonMapper Eigenschaften aus dem endgültigen Objekt entfernt, wenn sie nicht in den JSON-Daten enthalten waren:
$ jm = new JsonMapper ();
$ jm -> bRemoveUndefinedAttributes = true ;
$ jm -> map (...); Sie können die Zuordnung zu privaten und geschützten Eigenschaften und Setter-Methoden zulassen, indem Sie $bIgnoreVisibility auf true setzen:
$ jm = new JsonMapper ();
$ jm -> bIgnoreVisibility = true ;
$ jm -> map (...); Wenn der Typ einer Variablen eine Klasse ist und JSON-Daten ein einfacher Typ wie string sind, kann JsonMapper diesen Wert an den Konstruktor der Klasse übergeben, wenn er entsprechend konfiguriert ist:
$ jm = new JsonMapper ();
$ jm -> bStrictObjectTypeChecking = false ;
$ jm -> map (...);Dies kann verwendet werden, um DateTime-Objekte automatisch aus Datumszeichenfolgen zu initialisieren.
Das Deaktivieren dieser strengen Objekttypprüfungen kann jedoch zu Problemen führen:
@required -Eigenschaften werden nicht gefülltNotiz
Der Standardwert wurde in Version 5 von false auf true geändert, um die Sicherheit zu erhöhen.
Jetzt müssen Sie sich anmelden, wenn Sie einfache Typen an den Klassenkonstruktor übergeben möchten.
map() Möglicherweise möchten Sie Array-Daten an map() übergeben, die Sie durch den Aufruf erhalten haben
json_decode ( $ jsonString , true ) Standardmäßig löst JsonMapper eine Ausnahme aus, da map() ein Objekt als ersten Parameter erfordert. Sie können dies umgehen, indem Sie $bEnforceMapType auf false setzen:
$ jm = new JsonMapper ();
$ jm -> bEnforceMapType = false ;
$ jm -> map (...);JsonMapper kann eine benutzerdefinierte Methode direkt für jedes Objekt aufrufen, nachdem die Zuordnung abgeschlossen ist:
$ jm = new JsonMapper ();
$ jm -> postMappingMethod = ' afterMapping ' ;
$ jm -> map (...); Jetzt wird afterMapping() für jedes zugeordnete Objekt aufgerufen (sofern die Klasse über diese Methode verfügt).
Sie können dem Post-Mapping-Callback zusätzliche Argumente übergeben:
$ jm = new JsonMapper ();
$ jm -> postMappingMethod = ' afterMapping ' ;
$ jm -> postMappingMethodArguments = [ 23 , ' foo ' ];
$ jm -> map (...);Über Composer von Packagist:
$ Composer erfordert Netresearch/Jsonmapper
Alternativen
JsonMapper ist unter OSL 3.0 lizenziert.
JsonMapper folgt den PEAR-Codierungsstandards.
Christian Weiske, cweiske.de