Döküm ile, PHP içine JSON deserializing?

7 Cevap php

Ben 'isim' ve 'şifre' özellikleri, ve bir 'tasarruf' yöntemi ile bir kullanıcı sınıfı olduğunu varsayalım. Json_encode üzerinden JSON için bu sınıfın bir nesne seri hale getirilirken, yöntemi doğru atlanır ve ben {'isim': 'TestName', 'şifre': 'testPassword'} gibi bir şey ile sonuna kadar.

Json_decode yoluyla deserializing Ancak, bunun yerine mantıklı bir kullanıcı nesnesi, bir stdclass nesne ile sona ama bu nesnenin 'tasarruf' yöntemi yoksun demektir. Bir Kanala çıkan nesne artığını, ya da ben bekliyorum ne tür bir nesne olarak json_decode bazı ipucu sağlamak için herhangi bir yolu var mı?

7 Cevap

Ben bu işlemek için en iyi yolu, doğrudan veya bir fabrika aracılığıyla yapıcısı aracılığıyla olacağını düşünüyorum:

class User
{
   public $username;
   public $nestedObj; //another class that has a constructor for handling json
   ...

   // This could be make private if the factories below are used exclusively
   // and then make more sane constructors like:
   //     __construct($username, $password)
   public function __construct($mixed)
   {
       if (is_object($mixed)) {
           if (isset($mixed->username))
               $this->username = $mixed->username;
           if (isset($mixed->nestedObj) && is_object($mixed->nestedObj))
               $this->nestedObj = new NestedObject($mixed->nestedObj);
           ...
       } else if (is_array($mixed)) {
           if (isset($mixed['username']))
               $this->username = $mixed['username'];
           if (isset($mixed['nestedObj']) && is_array($mixed['nestedObj']))
               $this->nestedObj = new NestedObj($mixed['nestedObj']);
           ...
       }
   }
   ...

   public static fromJSON_by_obj($json)
   {
       return new self(json_decode($json));
   }

   public static fromJSON_by_ary($json)
   {
       return new self(json_decode($json, TRUE)); 
   }
}

Kısa cevap: Hayır (ben değil * biliyorum)

Uzun cevap: json_encode, sadece kamu değişkenleri seri olacak. Eğer başı görebileceğiniz gibi JSON spec, hayır "fonksiyonu" veri türü vardır. Bunlar yöntemleri JSON nesne içine tefrika değil neden her ikisi de nedenleri vardır.

Ryan Graham doğru - olmayan stdClass örnekleri olarak yeniden oluşturmak, bu nesneler için tek yolu onları post-deserialization yeniden yaratmaktır.

Örnek

<?php

class Person
{
    public $firstName;
    public $lastName;

    public function __construct( $firstName, $lastName )
    {
    	$this->firstName = $firstName;
    	$this->lastName = $lastName;
    }

    public static function createFromJson( $jsonString )
    {
    	$object = json_decode( $jsonString );
    	return new self( $object->firstName, $object->lastName );
    }

    public function getName()
    {
    	return $this->firstName . ' ' . $this->lastName;
    }
}

$p = new Person( 'Peter', 'Bailey' );
$jsonPerson = json_encode( $p );

$reconstructedPerson = Person::createFromJson( $jsonPerson );

echo $reconstructedPerson->getName();

Eğer gerçekten JSON verileri gerekmedikçe Alternatif olarak, sadece normal serialization kullanmak ve ek özelleştirme ulaşmak için __sleep() and __wakeup() hooks kullanabiliyorlar.

* ise a previous question of my own bunu json_encode giriş / çıkış (özelleştirmek için SPL arayüzleri bazı uygulamak önerdi) ama benim testler yabani kaz kovalayan olmak için bu ortaya çıktı.

Yazdığım bu sınıf bir göz atın:

https://github.com/mindplay-dk/jsonfreeze/blob/master/mindplay/jsonfreeze/JsonSerializer.php

Bu sınıf adını depolamak için '# tipi' adlı bir JSON nesne özelliği tutar, ve burada açıklanan bazı sınırlamaları vardır:

Serialize/unserialize PHP object-graph to JSON (partially working solution, needs help)

Ben JSON mükemmel kabul edilebilir ve hatta arzu edilir fonksiyonları serileştirme desteklemiyor farkında değilim. Benim sınıfları şu anda JavaScript ile iletişim değer nesneler olarak kullanılan ve işlevleri hiçbir anlam tutun (ve normal serileştirme işlevleri kullanılabilir değildir).

Bu sınıflara ait işlevselliği artırır Ancak, gerçek sınıf içinde (bu durumda bir Kullanıcı save () gibi) kendi kullanım fonksiyonlarını kapsüllenmesinde bana mantıklı. Bu da kesinlikle değer olsa nesneleri ve benim yukarıda belirtilen sorun haline çalıştırın orası artık değilsin demek.

Ben bir fikir json dize içinde belirtilen sınıf adı olurdu ve muhtemelen böyle sona ereceğini:

$string = '{"name": "testUser", "password": "testPassword", "class": "User"}';
$object = json_decode ($string);
$user = ($user->class) $object;

Ve ters json_encode sırasında / sonrasında sınıf özelliğini ayarlayarak olacaktır. Ben, biraz kıvrık biliyorum, ama ben sadece birlikte ilgili kodu tutmaya çalışıyorum. Muhtemelen yine sınıfların dışında benim yarar fonksiyonları alarak bitireceğiz; modifiye yapıcı yaklaşım biraz opak görünüyor ve iç içe nesneler ile sorun haline çalışır.

Ancak, bu ve gelecekteki herhangi bir geribildirim takdir ediyorum.

Bazı tür bir FactoryClass oluşturabilirsiniz:

function create(array $data)  
{
    $user = new User();
    foreach($data as $k => $v) {
        $user->$k = $v;
    }
    return $user;
}

Bu istediğin çözüm gibi değil, ama bu iş bitmiş olur.

Doğrudan soruyu yanıtlamak için, hayır, hayır json_encode / json_decode ile yapmak oldu orada. JSON tasarlanmış ve bilgi kodlama için bir biçimi olduğu belirtilen değil, nesneleri seri hale edildi. PHP işlevi ötesine gitmez.

Eğer JSON nesneleri yeniden ilgileniyorsanız, olası bir çözüm, bu şöyle bir stdClass / dize kabul eder ve değişkenleri doldurur hiyerarşinizdeki tüm nesneler üzerinde statik bir yöntemdir

//semi pseudo code, not tested
static public function createFromJson($json){
	//if you pass in a string, decode it to an object
	$json = is_string($json) ? json_decode($json) : $json;

	foreach($json as $key=>$value){
		$object = new self();
		if(is_object($value)){
			$object->{$key} = parent::createFromJson($json);
		}
		else{
			$object->{$key} = $value;
		}
	}

	return $object;
}

Bunu test etmedi, ama karşısında fikir alır umuyoruz. İdeal olarak, tüm nesneleri (genellikle "class Object" adında), bazı temel nesne uzanan bu yüzden sadece tek bir yerde bu kodu ekleyebilirsiniz.

Kendini JSON değilse bazı kütüphane, - ben bu raf işlevselliği kapalı, sadece standart olmadığını biraz dehşete söylemeliyim. Neden wouldn't Her iki tarafta aslında benzer nesneleri olmasını istiyorsanız? (Bildiğim kadarıyla JSON olarak zaten size izin verir)

Ben burada bir şey eksik? Bunu yapan bir kütüphane var mı? (AFAICT [tutumluluk, protokol tamponlar, avro] hiçbiri aslında benim problem için, ben JS en ilgileniyorum javascript için API'leri var <-> PHP, biraz da JS <->. Python.)