Saya menyukai saran Anda, hanya untuk berkomentar bahwa itu tidak akan berfungsi dengan objek bersarang (selain STDClass atau objek yang dikonversi)
javier_domenech
36
Kami membangun JsonMapper untuk memetakan objek JSON ke kelas model kami sendiri secara otomatis. Ini berfungsi dengan baik dengan objek bersarang / anak.
Ini hanya bergantung pada informasi jenis docblock untuk pemetaan, yang kebanyakan properti kelas miliki:
<?php$mapper = new JsonMapper();
$contactObject = $mapper->map(
json_decode(file_get_contents('http://example.org/contact.json')),
new Contact()
);
?>
Bisakah Anda menjelaskan lisensi OSL3? Jika saya menggunakan JsonMapper di situs web, haruskah saya merilis kode sumber situs web itu? Jika saya menggunakan JsonMapper dalam kode di perangkat yang saya jual, apakah semua kode perangkat itu harus open source?
EricP
1
Tidak, Anda hanya perlu menerbitkan perubahan yang Anda lakukan pada JsonMapper itu sendiri.
cweiske
29
Anda bisa melakukannya - itu kludge tetapi sangat mungkin. Kami harus melakukannya ketika kami mulai menyimpan barang-barang di couchbase.
$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
Dalam tolok ukur kami, ini jauh lebih cepat daripada mencoba mengulang melalui semua variabel kelas.
Peringatan: Tidak akan berfungsi untuk objek bertingkat selain stdClass
Edit: perhatikan sumber data, sangat disarankan agar Anda tidak melakukan ini dengan data tidak tepercaya dari pengguna tanpa analisis risiko yang cermat.
Apakah ini berfungsi dengan subclass yang dienkapsulasi. Misalnya { "a": {"b":"c"} }, di mana objeknya aadalah kelas lain dan bukan hanya array asosiatif?
J-Rou
2
tidak, json_decode membuat objek stdclass, termasuk sub objek, jika Anda ingin memiliki objek lain, Anda harus meng-kludge setiap objek seperti di atas.
John Pettitt
Terima kasih, itulah yang saya bayangkan
J-Rou
Bagaimana kalau menggunakan solusi ini pada objek di mana konstruktor memiliki parameter. Saya tidak bisa membuatnya bekerja. Saya berharap seseorang dapat mengarahkan saya ke arah yang benar agar solusi ini berfungsi dengan objek yang memiliki konstruktor khusus dengan parameter.
Sintaksnya tidak bergantung pada versi JMS Serializer, melainkan pada versi PHP - mulai dari PHP5.5 Anda dapat menggunakan ::classnotasi: php.net/manual/en/…
Ivan Yarych
4
Anda dapat membuat pembungkus untuk objek Anda dan membuat pembungkus terlihat seperti objek itu sendiri. Dan itu akan bekerja dengan objek bertingkat.
<?phpclassObj{
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 = new Obj($std);
echo$o->s3->s2->s1; // you will have 777
useApp\Model\Person;
$person = new Person();
$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
Deserialisasi dari JSON ke Objek: (contoh ini menggunakan XML hanya untuk mendemonstrasikan fleksibilitas format)
Seperti yang dikatakan Gordon, itu tidak mungkin. Tetapi jika Anda mencari cara untuk mendapatkan string yang dapat didekode sebagai instance dari kelas give, Anda dapat menggunakan serialize dan unserialize sebagai gantinya.
Ini sepertinya tidak menjawab pertanyaan itu. Jika ya, Anda harus memberikan penjelasan.
Felix Kling
1
Saya pernah membuat kelas dasar abstrak untuk tujuan ini. Sebut saja JsonConvertible. Ini harus membuat serial dan deserialisasi anggota publik. Hal ini dimungkinkan dengan menggunakan Refleksi dan pengikatan statis akhir.
Hanya dari ingatan, jadi mungkin tidak sempurna. Anda juga harus mengecualikan properti statis dan mungkin memberi kelas turunan kesempatan untuk membuat beberapa properti diabaikan saat diserialkan ke / dari json. Meski begitu, saya harap Anda mengerti.
JSON adalah protokol sederhana untuk mentransfer data antara berbagai bahasa pemrograman (dan itu juga merupakan bagian dari JavaScript) yang hanya mendukung jenis tertentu: angka, string, array / daftar, objek / dicts. Objek hanyalah peta key = value dan Array adalah daftar yang diurutkan.
Jadi tidak ada cara untuk mengekspresikan objek khusus dengan cara yang umum. Solusinya adalah dengan menentukan struktur di mana program Anda akan tahu bahwa itu adalah objek khusus.
Ini mungkin benar, tetapi pertanyaannya bukanlah menanyakan tentang merepresentasikan objek secara umum. Sepertinya dia punya tas JSON khusus yang memetakan ke kelas tertentu di salah satu atau kedua ujungnya. Tidak ada alasan Anda tidak dapat menggunakan JSON sebagai serialisasi eksplisit dari kelas bernama non-generik dengan cara ini. Menamainya seperti yang Anda lakukan boleh saja jika Anda menginginkan solusi umum, tetapi tidak ada salahnya juga jika Anda memiliki kontrak yang disepakati pada struktur JSON.
DougW
Ini bisa bekerja jika Anda mengimplementasikan Serializable di akhir encoding, dan memiliki persyaratan di akhir decoding. Bahkan bisa bekerja dengan subclass jika diatur dengan benar.
Ini bekerja dengan sempurna untuk kasus penggunaan saya. Namun tanggapan Yevgeniy Afanasyev tampaknya sama menjanjikannya bagi saya. Mungkin saja kelas Anda memiliki "konstruktor" tambahan, seperti:
publicstaticfunctionwithJson(string$json) {
$instance = newstatic();
// Do your thingreturn$instance;
}
EDIT: Saya telah menggunakan karriereat / json-decoder untuk beberapa waktu sekarang, dan saya sama sekali tidak mengalami masalah dengannya. Ringan dan sangat mudah dikembangkan. Berikut adalah contoh pengikatan yang saya tulis untuk deserialisasi JSON menjadi objek Carbon / CarbonImmutable.
Jawaban:
Tidak otomatis. Tapi Anda bisa melakukannya dengan cara lama.
$data = json_decode($json, true); $class = new Whatever(); foreach ($data as $key => $value) $class->{$key} = $value;
Atau sebagai alternatif, Anda dapat membuatnya lebih otomatis:
class Whatever { public function set($data) { foreach ($data AS $key => $value) $this->{$key} = $value; } } $class = new Whatever(); $class->set($data);
Sunting : menjadi sedikit lebih menarik:
class JSONObject { public function __construct($json = false) { if ($json) $this->set(json_decode($json, true)); } public function set($data) { foreach ($data AS $key => $value) { if (is_array($value)) { $sub = new JSONObject; $sub->set($value); $value = $sub; } $this->{$key} = $value; } } } // These next steps aren't necessary. I'm just prepping test data. $data = array( "this" => "that", "what" => "who", "how" => "dy", "multi" => array( "more" => "stuff" ) ); $jsonString = json_encode($data); // Here's the sweetness. $class = new JSONObject($jsonString); print_r($class);
sumber
Kami membangun JsonMapper untuk memetakan objek JSON ke kelas model kami sendiri secara otomatis. Ini berfungsi dengan baik dengan objek bersarang / anak.
Ini hanya bergantung pada informasi jenis docblock untuk pemetaan, yang kebanyakan properti kelas miliki:
<?php $mapper = new JsonMapper(); $contactObject = $mapper->map( json_decode(file_get_contents('http://example.org/contact.json')), new Contact() ); ?>
sumber
Anda bisa melakukannya - itu kludge tetapi sangat mungkin. Kami harus melakukannya ketika kami mulai menyimpan barang-barang di couchbase.
$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
Dalam tolok ukur kami, ini jauh lebih cepat daripada mencoba mengulang melalui semua variabel kelas.
Peringatan: Tidak akan berfungsi untuk objek bertingkat selain stdClass
Edit: perhatikan sumber data, sangat disarankan agar Anda tidak melakukan ini dengan data tidak tepercaya dari pengguna tanpa analisis risiko yang cermat.
sumber
{ "a": {"b":"c"} }
, di mana objeknyaa
adalah kelas lain dan bukan hanya array asosiatif?Anda dapat menggunakan pustaka Serializer J ohannes Schmitt .
$serializer = JMS\Serializer\SerializerBuilder::create()->build(); $object = $serializer->deserialize($jsonData, 'MyNamespace\MyObject', 'json');
Dalam versi terbaru serializer JMS, sintaksnya adalah:
$serializer = SerializerBuilder::create()->build(); $object = $serializer->deserialize($jsonData, MyObject::class, 'json');
sumber
::class
notasi: php.net/manual/en/…Anda dapat membuat pembungkus untuk objek Anda dan membuat pembungkus terlihat seperti objek itu sendiri. Dan itu akan bekerja dengan objek bertingkat.
<?php class Obj { public $slave; public function __get($key) { return property_exists ( $this->slave , $key ) ? $this->slave->{$key} : null; } public function __construct(stdClass $slave) { $this->slave = $slave; } } $std = json_decode('{"s3":{"s2":{"s1":777}}}'); $o = new Obj($std); echo $o->s3->s2->s1; // you will have 777
sumber
Tidak, ini tidak mungkin dilakukan mulai PHP 5.5.1.
Satu-satunya hal yang mungkin adalah memiliki
json_decode
array asosiasi yang dikembalikan, bukan objek StdClass.sumber
Anda dapat melakukannya dengan cara di bawah ini ..
<?php class CatalogProduct { public $product_id; public $sku; public $name; public $set; public $type; public $category_ids; public $website_ids; function __construct(array $data) { foreach($data as $key => $val) { if(property_exists(__CLASS__,$key)) { $this->$key = $val; } } } }
?>
Untuk detail selengkapnya, kunjungi create-custom-class-in-php-from-json-or-array
sumber
Saya terkejut belum ada yang menyebutkan ini.
Gunakan komponen Symfony Serializer: https://symfony.com/doc/current/components/serializer.html
Membuat serial dari Object ke JSON:
use App\Model\Person; $person = new Person(); $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
Deserialisasi dari JSON ke Objek: (contoh ini menggunakan XML hanya untuk mendemonstrasikan fleksibilitas format)
use App\Model\Person; $data = <<<EOF <person> <name>foo</name> <age>99</age> <sportsperson>false</sportsperson> </person> EOF; $person = $serializer->deserialize($data, Person::class, 'xml');
sumber
Gunakan Refleksi :
function json_decode_object(string $json, string $class) { $reflection = new ReflectionClass($class); $instance = $reflection->newInstanceWithoutConstructor(); $json = json_decode($json, true); $properties = $reflection->getProperties(); foreach ($properties as $key => $property) { $property->setAccessible(true); $property->setValue($instance, $json[$property->getName()]); } return $instance; }
sumber
Seperti yang dikatakan Gordon, itu tidak mungkin. Tetapi jika Anda mencari cara untuk mendapatkan string yang dapat didekode sebagai instance dari kelas give, Anda dapat menggunakan serialize dan unserialize sebagai gantinya.
class Foo { protected $bar = 'Hello World'; function getBar() { return $this->bar; } } $string = serialize(new Foo); $foo = unserialize($string); echo $foo->getBar();
sumber
Saya pernah membuat kelas dasar abstrak untuk tujuan ini. Sebut saja JsonConvertible. Ini harus membuat serial dan deserialisasi anggota publik. Hal ini dimungkinkan dengan menggunakan Refleksi dan pengikatan statis akhir.
abstract class JsonConvertible { static function fromJson($json) { $result = new static(); $objJson = json_decode($json); $class = new \ReflectionClass($result); $publicProps = $class->getProperties(\ReflectionProperty::IS_PUBLIC); foreach ($publicProps as $prop) { $propName = $prop->name; if (isset($objJson->$propName) { $prop->setValue($result, $objJson->$propName); } else { $prop->setValue($result, null); } } return $result; } function toJson() { return json_encode($this); } } class MyClass extends JsonConvertible { public $name; public $whatever; } $mine = MyClass::fromJson('{"name": "My Name", "whatever": "Whatever"}'); echo $mine->toJson();
Hanya dari ingatan, jadi mungkin tidak sempurna. Anda juga harus mengecualikan properti statis dan mungkin memberi kelas turunan kesempatan untuk membuat beberapa properti diabaikan saat diserialkan ke / dari json. Meski begitu, saya harap Anda mengerti.
sumber
JSON adalah protokol sederhana untuk mentransfer data antara berbagai bahasa pemrograman (dan itu juga merupakan bagian dari JavaScript) yang hanya mendukung jenis tertentu: angka, string, array / daftar, objek / dicts. Objek hanyalah peta key = value dan Array adalah daftar yang diurutkan.
Jadi tidak ada cara untuk mengekspresikan objek khusus dengan cara yang umum. Solusinya adalah dengan menentukan struktur di mana program Anda akan tahu bahwa itu adalah objek khusus.
Berikut contohnya:
{ "cls": "MyClass", fields: { "a": 123, "foo": "bar" } }
Ini dapat digunakan untuk membuat instance dari
MyClass
dan mengatur bidanga
danfoo
ke123
dan"bar"
.sumber
Saya melanjutkan dan menerapkan jawaban John Petit , sebagai fungsi ( inti ):
function json_decode_to(string $json, string $class = stdClass::class, int $depth = 512, int $options = 0) { $stdObj = json_decode($json, false, $depth, $options); if ($class === stdClass::class) return $stdObj; $count = strlen($class); $temp = serialize($stdObj); $temp = preg_replace("@^O:8:\"stdClass\":@", "O:$count:\"$class\":", $temp); return unserialize($temp); }
Ini bekerja dengan sempurna untuk kasus penggunaan saya. Namun tanggapan Yevgeniy Afanasyev tampaknya sama menjanjikannya bagi saya. Mungkin saja kelas Anda memiliki "konstruktor" tambahan, seperti:
public static function withJson(string $json) { $instance = new static(); // Do your thing return $instance; }
Ini juga terinspirasi oleh jawaban ini .
EDIT: Saya telah menggunakan karriereat / json-decoder untuk beberapa waktu sekarang, dan saya sama sekali tidak mengalami masalah dengannya. Ringan dan sangat mudah dikembangkan. Berikut adalah contoh pengikatan yang saya tulis untuk deserialisasi JSON menjadi objek Carbon / CarbonImmutable.
sumber