Mengambil data yang diambil dari layanan web JSON dan mengubahnya menjadi objek dan array bersarang - menggunakan kelas model Anda sendiri.
Dimulai dari objek dasar, ia memetakan data JSON pada properti kelas, mengubahnya menjadi tipe atau objek sederhana yang benar.
Ini seperti pemetaan parameter SOAP asli yang diberikan SoapClient
PHP kepada Anda, tetapi untuk JSON. Itu tidak bergantung pada skema apa pun, hanya definisi kelas PHP Anda.
Deteksi tipe bekerja dengan mengurai deklarasi tipe dan anotasi @var
docblock dari properti kelas, serta petunjuk tipe dalam metode penyetel.
Anda tidak perlu mengubah kelas model Anda dengan menambahkan kode spesifik JSON; ini bekerja secara otomatis dengan menguraikan docblock yang sudah ada.
Perpustakaan ini tidak memiliki ketergantungan.
Kata Kunci : deserialisasi, hidrasi
Isi
map()
Kelas model perlu ditulis dengan tangan
Karena JsonMapper tidak bergantung pada informasi skema apa pun (misalnya dari json-schema), kelas model tidak dapat dibuat secara otomatis.
netresearch/jsonmapper
dengan composerJsonMapper
map
atau mapArray
, bergantung pada data AndaMemetakan objek normal:
<?php
require ' autoload.php ' ;
$ mapper = new JsonMapper ();
$ contactObject = $ mapper -> map ( $ jsonContact , new Contact ());
// or as classname
$ contactObject = $ mapper -> map ( $ jsonContact , Contact::class);
Memetakan array objek:
<?php
require ' autoload.php ' ;
$ mapper = new JsonMapper ();
$ contactsArray = $ mapper -> mapArray (
$ jsonContacts , array (), ' Contact '
);
Daripada array()
Anda juga dapat menggunakan ArrayObject
dan kelas turunan, serta kelas yang mengimplementasikan ArrayAccess
.
JSON dari layanan web buku alamat:
{
"name" : "Sheldon Cooper" ,
"address" : {
"street" : "2311 N. Los Robles Avenue" ,
"city" : "Pasadena"
}
}
Kelas Contact
lokal Anda:
<?php
class Contact
{
/**
* Full name
*/
public string $ name ;
public ? Address $ address ;
}
Kelas Address
lokal Anda:
<?php
class Address
{
public $ street ;
public $ city ;
public function getGeoCoords ()
{
//do something with $street and $city
}
}
Kode aplikasi Anda:
<?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
menggunakan beberapa sumber untuk mendeteksi tipe properti yang benar dengan urutan berikut:
Metode penyetel ( set
+ ucwords($propertyname)
)
Garis bawah " _
" dan tanda hubung " -
" membuat huruf berikutnya menjadi huruf besar. Properti foo_bar-baz
mengarah ke metode penyetel setFooBarBaz
.
Jika ada petunjuk tipe pada tanda tangan metode, maka tipenya digunakan:
fungsi publik setPerson(Hubungi $person) {...}
Docblock metode diperiksa untuk anotasi @param $type
:
/** * @param Kontak $person Kontak utama untuk aplikasi ini */ fungsi publik setPerson($orang) {...}
Jika tidak ada jenis yang dapat dideteksi, nilai JSON biasa diteruskan ke metode penyetel.
Tipe properti kelas (sejak PHP 7.4):
Kontak publik $orang;
Jenis promosi properti konstruktor (sejak PHP 8.0):
fungsi publik __construct(Kontak $person yang dilindungi) {}
@var $type
docblock anotasi properti kelas:
/** * @var aplikasisayamodelKontak */ publik $orang;
Properti harus bersifat publik agar dapat digunakan secara langsung. Anda juga dapat menggunakan $bIgnoreVisibility untuk memanfaatkan properti yang dilindungi dan pribadi.
Jika tidak ada jenis yang dapat dideteksi, properti akan mendapatkan kumpulan nilai JSON biasa.
Jika properti tidak dapat ditemukan, JsonMapper mencoba menemukan properti tersebut dengan tidak membedakan huruf besar dan kecil. Properti JSON isempty
kemudian akan dipetakan ke properti PHP isEmpty
.
Catatan
Anda harus menyediakan namespace yang sepenuhnya memenuhi syarat agar tipe tersebut dapat berfungsi. Nama kelas relatif dievaluasi dalam konteks namespace kelas saat ini, TIDAK memperhatikan impor apa pun yang mungkin ada.
PHP tidak menyediakan impor melalui Refleksi; teks komentar hanya berisi teks literal dari tipe tersebut. Untuk alasan kinerja, JsonMapper tidak mengurai kode sumbernya sendiri untuk mendeteksi dan memperluas impor apa pun.
Tipe sederhana
string
bool
, boolean
int
, integer
double
, float
array
object
mixed
Nama kelas, dengan dan tanpa namespace
Contact
- pengecualian akan diberikan jika nilai JSON adalah null
Array tipe sederhana dan nama kelas:
int[]
Contact[]
Array multidimensi:
int[][]
TreeDeePixel[][][]
ArrayObjects dengan tipe sederhana dan nama kelas:
ContactList[Contact]
NumberList[int]
Enum yang didukung, dengan dan tanpa namespace
Suit:string|Suit:int
- pengecualian akan dilemparkan jika nilai JSON tidak ada dalam enum
Jenis yang tidak dapat dibatalkan:
int|null
atau ?int
- akan menjadi null
jika nilai dalam JSON adalah null
, jika tidak maka akan menjadi bilangan bulatContact|null
atau ?Contact
- akan menjadi null
jika nilai dalam JSON adalah null
, jika tidak maka akan menjadi objek bertipe Contact
ArrayObjects dan kelas perluasan diperlakukan sebagai array.
Variabel tanpa tipe atau dengan tipe mixed
akan mendapatkan nilai JSON yang ditetapkan secara langsung tanpa konversi apa pun.
Lihat dokumentasi tipe phpdoc untuk informasi lebih lanjut.
Catatan
Fitur ini dinonaktifkan secara default karena alasan keamanan sejak versi 5. Lihat $bStrictObjectTypeChecking untuk detailnya.
Ketika sebuah objek akan dibuat tetapi JSON hanya berisi tipe sederhana (misalnya string, float, boolean), nilai ini diteruskan ke konstruktor kelas. Contoh:
Kode PHP:
public DateTime $ date ;
JSON:
{ "date" : "2014-05-15" }
Ini akan mengakibatkan new DateTime('2014-05-15')
dipanggil.
Ketika variabel didefinisikan sebagai objek kelas atau antarmuka abstrak, JsonMapper biasanya akan mencoba membuat instance variabel tersebut secara langsung dan mogok.
Dengan menggunakan properti $classMap
JsonMapper, Anda dapat menentukan kelas mana yang akan dipakai:
$ jm = new JsonMapper ();
$ jm -> classMap [ ' Foo ' ] = ' Bar ' ;
$ jm -> map (...);
Ini akan membuat objek bertipe Bar
ketika variabel didefinisikan bertipe Foo
.
Dimungkinkan juga untuk menggunakan callable jika kelas implementasi aktual perlu ditentukan secara dinamis (misalnya dalam kasus gabungan). Kelas yang dipetakan ('Foo' pada contoh di bawah) dan data Json diteruskan sebagai parameter ke dalam panggilan.
$ 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 memunculkan pengecualian ketika properti JSON adalah null
, kecuali properti kelas PHP memiliki tipe yang dapat dibatalkan - misalnya Contact|null
atau ?Contact
.
Jika API Anda berisi banyak bidang yang mungkin bernilai null
dan Anda tidak ingin membuat semua definisi tipe Anda dapat dibatalkan, setel:
$ jm -> bStrictNullTypes = false ;
Sejak versi 5.0.0, nilai null
dalam array mengarah ke JsonMapper_Exception
kecuali tipenya dapat dibatalkan - misalnya array[?string]
atau array[string|null]
.
Untuk mendapatkan kembali perilaku sebelumnya (mengizinkan null meskipun tidak dinyatakan demikian) setel:
$ jm -> bStrictNullTypesInArrays = false ;
Metode setLogger()
JsonMapper mendukung semua instance logger yang kompatibel dengan PSR-3.
Peristiwa yang dicatat:
Selama pengembangan, API sering berubah. Untuk mendapatkan pemberitahuan tentang perubahan tersebut, JsonMapper dapat dikonfigurasi untuk memberikan pengecualian jika ada data yang hilang atau belum diketahui.
Saat JsonMapper melihat properti dalam data JSON yang tidak ditentukan di kelas PHP, Anda dapat membiarkannya mengeluarkan pengecualian dengan menyetel $bExceptionOnUndefinedProperty
:
$ jm = new JsonMapper ();
$ jm -> bExceptionOnUndefinedProperty = true ;
$ jm -> map (...);
Anda juga dapat memilih untuk menangani sendiri properti tersebut dengan menyetel callable ke $undefinedPropertyHandler
:
/**
* 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 (...);
Atau jika Anda membiarkan JsonMapper menangani penyetel untuk Anda, Anda dapat mengembalikan string dari $undefinedPropertyHandler
yang akan digunakan sebagai nama properti.
/**
* 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 (...);
Catatan
Ini hanya berfungsi ketika $bStrictObjectTypeChecking tetap diaktifkan.
Properti di kelas PHP Anda dapat ditandai sebagai "wajib" dengan memasukkan @required
di blok dokumennya:
/**
* @var string
* @required
*/
public $ someDatum ;
Jika data JSON tidak berisi properti ini, JsonMapper akan menampilkan JsonMapper_Exception
saat $bExceptionOnMissingData
diaktifkan:
$ jm = new JsonMapper ();
$ jm -> bExceptionOnMissingData = true ;
$ jm -> map (...);
Opsi $bRemoveUndefinedAttributes
menyebabkan JsonMapper menghapus properti dari objek akhir jika properti tersebut belum ada dalam data JSON:
$ jm = new JsonMapper ();
$ jm -> bRemoveUndefinedAttributes = true ;
$ jm -> map (...);
Anda dapat mengizinkan pemetaan ke properti pribadi dan dilindungi serta metode penyetel dengan menyetel $bIgnoreVisibility
ke true:
$ jm = new JsonMapper ();
$ jm -> bIgnoreVisibility = true ;
$ jm -> map (...);
Ketika tipe variabel adalah kelas dan data JSON adalah tipe sederhana seperti string
, JsonMapper dapat meneruskan nilai ini ke konstruktor kelas ketika dikonfigurasi untuk melakukannya:
$ jm = new JsonMapper ();
$ jm -> bStrictObjectTypeChecking = false ;
$ jm -> map (...);
Ini dapat digunakan untuk menginisialisasi objek DateTime secara otomatis dari string tanggal.
Namun, menonaktifkan pemeriksaan tipe objek yang ketat ini dapat menimbulkan masalah:
@required
tidak akan diisiCatatan
Nilai default diubah dari false
menjadi true
di versi 5 untuk meningkatkan keamanan.
Sekarang Anda harus ikut serta jika ingin meneruskan tipe sederhana ke konstruktor kelas.
map()
Anda mungkin ingin meneruskan data array ke map()
yang Anda dapatkan dengan menelepon
json_decode ( $ jsonString , true )
Secara default, JsonMapper akan mengeluarkan pengecualian karena map()
memerlukan objek sebagai parameter pertama. Anda dapat menghindarinya dengan menyetel $bEnforceMapType
ke false
:
$ jm = new JsonMapper ();
$ jm -> bEnforceMapType = false ;
$ jm -> map (...);
JsonMapper dapat memanggil metode khusus secara langsung pada setiap objek setelah pemetaan selesai:
$ jm = new JsonMapper ();
$ jm -> postMappingMethod = ' afterMapping ' ;
$ jm -> map (...);
Sekarang afterMapping()
dipanggil pada setiap objek yang dipetakan (jika kelas memiliki metode itu).
Anda dapat meneruskan argumen tambahan ke callback pasca-pemetaan:
$ jm = new JsonMapper ();
$ jm -> postMappingMethod = ' afterMapping ' ;
$ jm -> postMappingMethodArguments = [ 23 , ' foo ' ];
$ jm -> map (...);
Melalui Komposer dari Packagist:
$ komposer memerlukan netresearch/jsonmapper
Alternatif
JsonMapper dilisensikan di bawah OSL 3.0.
JsonMapper mengikuti Standar Pengkodean PEAR.
Christian Weiske, cweiske.de