programing

json_custom 클래스에 추가

goodsources 2022. 9. 6. 22:35
반응형

json_custom 클래스에 추가

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

JSON 객체를 자체 모델 클래스에 자동으로 매핑하는 JsonMapper를 구축했습니다.중첩된 개체/하위 개체와 함께 올바르게 작동합니다.

매핑은 대부분의 클래스 속성이 가지고 있는 docblock 유형 정보에만 의존합니다.

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

넌 할 수 있어 - 그건 크러지지만 완전히 가능해.소파 베이스에 물건을 보관하기 시작했을 때 우리는 해야 했다.

$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 이외의 중첩된 개체에서는 작동하지 않습니다.

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

요하네스 슈미트의 연재 도서관을 이용할 수도 있어

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

아직 아무도 이런 얘기를 안 했다니 놀랍네요

Symfony Serializer 구성 요소 사용: https://symfony.com/doc/current/components/serializer.html

개체에서 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

JSON에서 오브젝트로의 역직렬화: (이 예에서는 포맷의 유연성을 나타내기 위해서만 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
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를 참조하십시오.

오브젝트에 대한 래퍼를 만들고 래퍼를 오브젝트 자체처럼 만들 수 있습니다.다단계 객체와 함께 사용할 수 있습니다.

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

아니요, PHP 5.5.1에서는 불가능합니다.

가능한 것은 StdClass 오브젝트 대신 어소시에이트 어레이를 반환하는 것뿐입니다.

리플렉션 사용

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

이 목적을 위해 추상 기본 클래스를 만든 적이 있습니다.제이슨컨버터블이라고 하죠그것은 공공 구성원을 직렬화하고 직렬화를 취소해야 한다.이것은 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".

고든이 말한 것처럼 가능하지 않다.단, give 클래스의 인스턴스로 디코딩할 수 있는 문자열을 얻는 방법을 찾는 경우 대신 serialize 및 unserialize를 사용할 수 있습니다.

class Foo
{

    protected $bar = 'Hello World';

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

}

$string = serialize(new Foo);

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

John Petit의 답변을 함수(gist)로서 구현했습니다.

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

이것은 내 사용 사례에 딱 들어맞았다.그러나 예브게니 아파나스예프의 답변은 나에게 똑같이 유망해 보인다.다음과 같은 추가 "구성자"를 학급에 둘 수 있습니다.

public static function withJson(string $json) {
    $instance = new static();
    // Do your thing
    return $instance;
}

이것 또한 이 답변에서 영감을 얻었다.

편집: 저는 얼마 전부터 karriecreate/json-decoder를 사용하고 있습니다만, 전혀 문제가 없었습니다.가볍고 매우 쉽게 확장할 수 있습니다.다음은 JSON을 Carbon/CarbonImmmable 객체로 역직렬화하기 위해 작성한 바인딩의 입니다.

이 모든 것이, 일반적인 기능에의 영감을 주었습니다.

function loadJSON($Obj, $json)
{
     $dcod = json_decode($json);
     $prop = get_object_vars ( $dcod );
     foreach($prop as $key => $lock)
     {
        if(property_exists ( $Obj ,  $key ))
        {
            if(is_object($dcod->$key))
            {
                loadJSON($Obj->$key, json_encode($dcod->$key));
            }
            else
            {
                $Obj->$key = $dcod->$key;
            }
        }
    }
}

클래스 선언에서 호출:

class Bar{public $bar = " Boss";}
class Bas
{
    public $ber ;
    public $bas=" Boven"; 
    public function __construct() 
        {$this->ber = new Bar;}
}
class Baz
{
    public $bes ;
    public $baz=" Baaz";  
    public function __construct() 
        {$this->bes = new Bas;}
}

$Bazjson = '{"bes":{"ber":{"bar":"Baas"}}}';

$Bazobj = new Baz;

loadJSON($Bazobj, $Bazjson);
var_dump($Bazobj);

이것은 특히 타겟 클래스에 세터나 명명된 속성이 없는 경우에 효과가 있었습니다.

function cast($jsonstring, $class)
{
   //$class is a string like 'User'

    $json= json_decode($jsonstring,true);  //array
   
    $reflection = new ReflectionClass($class);
    $instance = $reflection->newInstanceWithoutConstructor();
    $keys = array_keys($json);

    foreach ($keys  as $key => $property) {
        $instance->{$property} =$json[$property];
    }

   // print_r($instance);

    return $instance;
}

언급URL : https://stackoverflow.com/questions/5397758/json-decode-to-custom-class

반응형