เป็นไปได้ไหมที่จะถอดรหัสสตริง json ไปยังวัตถุอื่นที่ไม่ใช่ stdClass
เป็นไปได้ไหมที่จะถอดรหัสสตริง json ไปยังวัตถุอื่นที่ไม่ใช่ stdClass
คำตอบ:
ไม่อัตโนมัติ แต่คุณสามารถทำเส้นทางแบบเก่าได้
$data = json_decode($json, true);
$class = new Whatever();
foreach ($data as $key => $value) $class->{$key} = $value;
หรือคุณสามารถทำให้อัตโนมัติมากขึ้น:
class Whatever {
public function set($data) {
foreach ($data AS $key => $value) $this->{$key} = $value;
}
}
$class = new Whatever();
$class->set($data);
แก้ไข : รับนักเล่นตัวน้อย:
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);
เราสร้างJsonMapperเพื่อแมปวัตถุ JSON กับคลาสโมเดลของเราเองโดยอัตโนมัติ ทำงานได้ดีกับวัตถุที่ซ้อนกัน / ลูก
มันอาศัยข้อมูลประเภท docblock สำหรับการแม็ปเท่านั้นซึ่งคุณสมบัติของคลาสส่วนใหญ่มีอยู่แล้ว:
<?php
$mapper = new JsonMapper();
$contactObject = $mapper->map(
json_decode(file_get_contents('http://example.org/contact.json')),
new Contact()
);
?>
คุณทำได้ - มันเป็นกากตะกอน แต่เป็นไปได้ทั้งหมด เราต้องทำเมื่อเราเริ่มจัดเก็บสิ่งต่างๆใน 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
ในเกณฑ์มาตรฐานของเราวิธีนี้เร็วกว่าการพยายามวนซ้ำผ่านตัวแปรคลาสทั้งหมด
Caveat: จะไม่ทำงานกับวัตถุที่ซ้อนกันนอกเหนือจาก stdClass
แก้ไข: โปรดจำไว้ว่าแหล่งข้อมูลขอแนะนำอย่างยิ่งว่าอย่าทำเช่นนี้กับข้อมูลที่ไม่น่าเชื่อถือจากผู้ใช้โดยไม่มีการวิเคราะห์ความเสี่ยงอย่างรอบคอบ
{ "a": {"b":"c"} }
ที่ออบเจ็กต์อยู่ในa
คลาสอื่นไม่ใช่แค่อาร์เรย์ที่เชื่อมโยงกัน?
คุณสามารถใช้เจohannes ห้องสมุด
$serializer = JMS\Serializer\SerializerBuilder::create()->build();
$object = $serializer->deserialize($jsonData, 'MyNamespace\MyObject', 'json');
ในซีเรียลไลเซอร์ JMS เวอร์ชันล่าสุดไวยากรณ์คือ:
$serializer = SerializerBuilder::create()->build();
$object = $serializer->deserialize($jsonData, MyObject::class, 'json');
::class
สัญกรณ์: php.net/manual/en/…
คุณสามารถสร้างกระดาษห่อหุ้มสำหรับวัตถุของคุณและทำให้กระดาษห่อหุ้มดูเหมือนว่าเป็นวัตถุนั้นเอง และจะทำงานกับวัตถุหลายระดับ
<?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
ฉันแปลกใจที่ไม่มีใครพูดถึงเรื่องนี้
ใช้ส่วนประกอบ Symfony Serializer: https://symfony.com/doc/current/components/serializer.html
การทำให้อนุกรมจาก Object เป็น 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
Deserializing จาก JSON เป็น Object: (ตัวอย่างนี้ใช้ XML เพื่อแสดงความยืดหยุ่นของรูปแบบ)
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');
ไม่เป็นไปไม่ได้ใน PHP 5.5.1
สิ่งเดียวที่เป็นไปได้คือการjson_decode
ส่งคืนอาร์เรย์เชื่อมโยงแทนวัตถุ StdClass
คุณสามารถทำได้ด้วยวิธีด้านล่าง ..
<?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;
}
}
}
}
?>
สำหรับรายละเอียดเพิ่มเติมโปรดไปที่ create-custom-class-in-php-from-json-or-array
ใช้การสะท้อนกลับ :
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;
}
อย่างที่กอร์ดอนบอกว่าเป็นไปไม่ได้ แต่ถ้าคุณกำลังมองหาวิธีรับสตริงที่สามารถถอดรหัสเป็นอินสแตนซ์ของคลาสGive ได้คุณสามารถใช้serializeและ Unserialize แทนได้
class Foo
{
protected $bar = 'Hello World';
function getBar() {
return $this->bar;
}
}
$string = serialize(new Foo);
$foo = unserialize($string);
echo $foo->getBar();
ฉันเคยสร้างคลาสฐานนามธรรมเพื่อจุดประสงค์นี้ เรียกว่า JsonConvertible ควรทำให้เป็นอนุกรมและ deserialize สมาชิกสาธารณะ สามารถทำได้โดยใช้ Reflection และการผูกแบบคงที่
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();
เพียงจากความทรงจำดังนั้นอาจจะไม่สมบูรณ์แบบ นอกจากนี้คุณจะต้องยกเว้นคุณสมบัติคงที่และอาจให้คลาสที่ได้รับมีโอกาสที่จะทำให้คุณสมบัติบางอย่างถูกละเว้นเมื่อต่ออนุกรมกับ / จาก json ฉันหวังว่าคุณจะได้รับความคิดอย่างไรก็ตาม
JSON เป็นโปรโตคอลง่ายๆในการถ่ายโอนข้อมูลระหว่างภาษาโปรแกรมต่างๆ (และยังเป็นส่วนย่อยของ JavaScript) ซึ่งรองรับเฉพาะบางประเภท: ตัวเลขสตริงอาร์เรย์ / รายการวัตถุ / คำสั่ง ออบเจ็กต์เป็นเพียงคีย์ = แมปค่าและอาร์เรย์เป็นรายการเรียงลำดับ
ดังนั้นจึงไม่มีวิธีใดที่จะแสดงออบเจ็กต์แบบกำหนดเองในลักษณะทั่วไป วิธีแก้ปัญหาคือการกำหนดโครงสร้างที่โปรแกรมของคุณจะรู้ว่าเป็นวัตถุที่กำหนดเอง
นี่คือตัวอย่าง:
{ "cls": "MyClass", fields: { "a": 123, "foo": "bar" } }
นี้สามารถนำมาใช้ในการสร้างตัวอย่างของMyClass
และการตั้งค่าเขตข้อมูลa
และfoo
การและ123
"bar"
ฉันดำเนินการต่อและใช้คำตอบของ John Petitเป็นฟังก์ชัน ( ส่วนสำคัญ ):
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);
}
สิ่งนี้ใช้ได้ดีกับกรณีการใช้งานของฉัน อย่างไรก็ตามคำตอบของ Yevgeniy Afanasyevดูเหมือนจะให้คำมั่นสัญญากับฉันอย่างเท่าเทียมกัน อาจเป็นไปได้ที่จะให้ชั้นเรียนของคุณมี "ตัวสร้าง" เพิ่มเติมดังนี้:
public static function withJson(string $json) {
$instance = new static();
// Do your thing
return $instance;
}
นี่เป็นแรงบันดาลใจจากคำตอบนี้เช่นกัน
แก้ไข: ฉันใช้karriereat / json-decoderมาระยะหนึ่งแล้วและฉันก็ไม่มีปัญหากับมันเลย มีน้ำหนักเบาและขยายได้ง่ายมาก นี่คือตัวอย่างของการผูกที่ฉันเขียนเพื่อแยก JSON ลงในวัตถุ Carbon / CarbonImmutable