programing tip

json_decode를 사용자 정의 클래스로

itbloger 2020. 10. 12. 07:19
반응형

json_decode를 사용자 정의 클래스로


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);

당신은 그것을 할 수 있습니다-그것은 kludge이지만 완전히 가능합니다. 소파베이스에 물건을 보관하기 시작했을 때해야했습니다.

$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 

벤치 마크에서 이것은 모든 클래스 변수를 반복하는 것보다 훨씬 빠릅니다.

주의 사항 : stdClass 이외의 중첩 된 개체에 대해서는 작동하지 않습니다.

편집 : 데이터 소스를 염두에 두십시오. 위험에 대한 세심한 분석 없이는 사용자의 신뢰할 수없는 데이터와 함께이 작업을 수행하지 않는 것이 좋습니다.


JSON 객체를 자체 모델 클래스에 자동으로 매핑하기 위해 JsonMapper구축 했습니다 . 중첩 / 자식 개체와 잘 작동합니다.

대부분의 클래스 속성에는 어쨌든 매핑을위한 docblock 유형 정보에만 의존합니다.

<?php
$mapper = new JsonMapper();
$contactObject = $mapper->map(
    json_decode(file_get_contents('http://example.org/contact.json')),
    new Contact()
);
?>

J ohannes Schmitt의 Serializer 라이브러리를 사용할 수 있습니다 .

$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');

아니요, PHP 5.5.1부터는 불가능합니다.

가능한 유일한 방법 json_decode은 StdClass 객체 대신에 연관 배열 반환하는 것입니다.


개체에 대한 래퍼를 만들고 래퍼를 개체 자체처럼 보이게 만들 수 있습니다. 그리고 그것은 다단계 개체와 함께 작동합니다.

<?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

Gordon이 말했듯이 불가능합니다. 그러나 제공 클래스의 인스턴스로 디코딩 할 수있는 문자열을 얻는 방법을 찾고 있다면 직렬화 및 직렬화 해제를 대신 사용할 수 있습니다 .

class Foo
{

    protected $bar = 'Hello World';

    function getBar() {
        return $this->bar;
    }

}

$string = serialize(new Foo);

$foo = unserialize($string);
echo $foo->getBar();

아래 방법으로 할 수 있습니다 ..

<?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;
            }
        }
    }
}

?>

For more details visit create-custom-class-in-php-from-json-or-array


I once created an abstract base class for this purpose. Let's call it JsonConvertible. It should serialize and deserialize the public members. This is possible using Reflection and late static binding.

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();

Just from memory, so probably not flawless. You will also have to exclude static properties and may give derived classes the chance to make some properties ignored when serialized to/from json. I hope you get the idea, nonetheless.


JSON is a simple protocol to transfer data between various programming languages (and it's also a subset of JavaScript) which supports just certain types: numbers, strings, arrays/lists, objects/dicts. Objects are just key=value maps and Arrays are ordered lists.

So there is no way to express custom objects in a generic way. The solution is defining a structure where your program(s) will know that it's a custom object.

Here's an example:

{ "cls": "MyClass", fields: { "a": 123, "foo": "bar" } }

This could be used to create an instance of MyClass and set the fields a and foo to 123 and "bar".


I think the simplest way is :

function mapJSON($json, $class){
$decoded_object = json_decode($json);
   foreach ($decoded_object as $key => $value) {
            $class->$key = $value;
   }
   return $class;}

참고URL : https://stackoverflow.com/questions/5397758/json-decode-to-custom-class

반응형