Jadi saya berkeliling php.net untuk informasi tentang serialisasi objek PHP ke JSON, ketika saya menemukan Antarmuka JsonSerializable baru . Ini hanya PHP> = 5.4 , dan saya menjalankan di lingkungan 5.3.x.
Bagaimana fungsionalitas semacam ini mencapai PHP <5,4 ?
Saya belum banyak bekerja dengan JSON, tetapi saya mencoba mendukung lapisan API dalam sebuah aplikasi, dan membuang objek data ( yang jika tidak akan dikirim ke tampilan ) ke dalam JSON akan menjadi sempurna.
Jika saya mencoba untuk membuat serial objek secara langsung, ia mengembalikan string JSON kosong; yang karena saya berasumsi json_encode()
tidak tahu apa yang harus dilakukan dengan objek tersebut. Haruskah saya rekursif mengurangi objek ke array, dan kemudian encode itu ?
Contoh
$data = new Mf_Data();
$data->foo->bar['hello'] = 'world';
echo json_encode($data)
menghasilkan benda kosong:
{}
var_dump($data)
namun, berfungsi seperti yang diharapkan:
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)
}
Tambahan
1)
Jadi ini adalah toArray()
fungsi yang saya buat untuk Mf_Data
kelas:
public function toArray()
{
$array = (array) $this;
array_walk_recursive($array, function (&$property) {
if ($property instanceof Mf_Data) {
$property = $property->toArray();
}
});
return $array;
}
Namun karena Mf_Data
objek juga memiliki referensi ke objek induknya ( berisi ), ini gagal dengan rekursi. Bekerja seperti pesona meskipun ketika saya menghapus _parent
referensi.
2)
Sebagai tindak lanjut, fungsi terakhir untuk mengubah objek simpul pohon kompleks yang saya gunakan adalah:
// 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)
Saya menindaklanjuti lagi, dengan implementasi yang sedikit lebih bersih. Menggunakan antarmuka untuk instanceof
pemeriksaan tampaknya jauh lebih bersih daripada method_exists()
( namun demikian method_exists()
juga pewarisan / implementasi lintas sektoral ).
Penggunaannya juga unset()
terlihat agak berantakan, dan tampaknya logika harus direfraktorkan ke metode lain. Namun, implementasi ini menyalin array properti ( karenaarray_diff_key
), jadi sesuatu yang perlu dipertimbangkan.
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'
)));
}
}
sumber
JsonSerializable
Jawaban:
edit : saat ini 2016-09-24, dan PHP 5.4 telah dirilis 2012-03-01, dan dukungan telah berakhir 2015-09-01. Namun, jawaban ini tampaknya mendapatkan suara positif. Jika Anda masih menggunakan PHP <5.4, Anda menimbulkan risiko keamanan dan membahayakan proyek Anda . Jika Anda tidak memiliki alasan kuat untuk tetap menggunakan <5.4, atau bahkan sudah menggunakan versi> = 5.4, jangan gunakan jawaban ini , dan cukup gunakan PHP> = 5.4 (atau, Anda tahu, yang terbaru) dan terapkan antarmuka JsonSerializable
Anda akan mendefinisikan sebuah fungsi, misalnya bernama
getJsonData();
, yang akan mengembalikan array,stdClass
objek, atau objek lain dengan parameter yang terlihat daripada yang privat / dilindungi, dan melakukan ajson_encode($data->getJsonData());
. Intinya, terapkan fungsi dari 5.4, tetapi panggil dengan tangan.Sesuatu seperti ini akan berfungsi, seperti
get_object_vars()
yang dipanggil dari dalam kelas, memiliki akses ke variabel privat / dilindungi:sumber
stdClass
? Saya berpikir ke arah Refleksi , tetapi jika tidak, saya hanya akan memikirkan sesuatu untuk melakukannya secara rekursif.getJsonData()
fungsi Anda, Anda bisa memanggilget_object_vars()
, dan mengulang hasil itu untuk mencari lebih banyak objek._parent
properti sehingga pohon tersebut dapat dilintasi ke root. Lihat hasil edit saya untuk pembaruan; mungkin saya harus mengajukan pertanyaan lain karena masalah ini sekarang disarikan dari aslinya.unset($array['_parent']);
sebelum berjalan harus melakukan triknya.$parent
sebagai data penggunaarray_walk_recursive()
. Sederhana itu indah! Juga,$array["\0class\0property"]
karena polusi null-byte karena saya menggunakan casting. Saya pikir saya akan beralih keget_object_vars()
.Dalam kasus yang paling sederhana, jenis petunjuk seharusnya berfungsi:
sumber
json_encode()
hanya akan menyandikan variabel anggota publik. jadi jika Anda ingin memasukkan pribadi setelah Anda harus melakukannya sendiri (seperti yang disarankan orang lain)sumber
Kode berikut melakukan pekerjaan menggunakan refleksi. Ini mengasumsikan Anda memiliki getter untuk properti yang ingin Anda serialisasi
sumber
Cukup terapkan Antarmuka yang diberikan oleh PHP JsonSerializable .
sumber
Karena tipe objek Anda adalah kustom, saya cenderung setuju dengan solusi Anda - memecahnya menjadi segmen yang lebih kecil menggunakan metode pengkodean (seperti JSON atau membuat serial konten), dan di sisi lain memiliki kode yang sesuai untuk membangun kembali objek.
sumber
Versi saya:
Penerapan:
JsonUtils: GitHub
sumber
Coba gunakan ini, ini bekerja dengan baik untuk saya.
sumber
Ubah ke jenis variabel Anda
private
menjadipublic
Ini sederhana dan lebih mudah dibaca.
Sebagai contoh
Tidak Bekerja;
Ini bekerja;
sumber
Saya membuat kelas penolong bagus yang mengubah objek dengan metode get menjadi array. Itu tidak bergantung pada properti, hanya metode.
Jadi saya memiliki objek ulasan berikut yang berisi dua metode:
Ulasan
Komentar
Skrip yang saya tulis akan mengubahnya menjadi array dengan properti yang terlihat seperti ini:
Sumber: PHP Serializer yang mengubah objek menjadi array yang dapat dikodekan ke JSON.
Yang harus Anda lakukan adalah membungkus json_encode di sekitar output.
Beberapa informasi tentang skrip:
sumber
Saya menghabiskan beberapa jam untuk masalah yang sama. Objek saya untuk dikonversi berisi banyak objek lain yang definisinya tidak boleh saya sentuh (API), jadi saya telah menemukan solusi yang bisa jadi lambat, tetapi saya menggunakannya untuk tujuan pengembangan.
Yang ini mengubah objek apa pun menjadi array
Ini mengubah objek apa pun menjadi stdClass
sumber
unlink($thisAnswer);