2011-03-22 25 views

Respuesta

3

No, esto no es posible a partir de PHP 5.5.1.

Lo único posible es tener matrices asociadas de retorno json_decode en lugar de los objetos StdClass.

0

Como Gordon dice que no es posible. Pero si está buscando una manera de obtener una cadena que se pueda decodificar como una instancia de una clase de entrega, puede usar serialize y deserializar en su lugar.

class Foo 
{ 

    protected $bar = 'Hello World'; 

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

} 

$string = serialize(new Foo); 

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

Esto no parece abordar la pregunta. Si lo hace, debe proporcionar alguna explicación. –

+0

Mejor explico mi punto: P –

70

No automáticamente. Pero puedes hacerlo a la antigua usanza.

$data = json_decode($json, true); 

$class = new Whatever(); 
foreach ($data as $key => $value) $class->{$key} = $value; 

O, alternativamente, podría hacer que más automático:

class Whatever { 
    public function set($data) { 
     foreach ($data AS $key => $value) $this->{$key} = $value; 
    } 
} 

$class = new Whatever(); 
$class->set($data); 

Editar: conseguir un poco más de lujo:

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

Me gustas tus sugerencias, solo para señalar que no funcionará con objetos anidados (que no sean STDClass o el objeto convertido) – vivoconunxino

-1

JSON es un protocolo simple para transferir datos entre diferentes lenguajes de programación (y también es un subconjunto de JavaScript) que solo admite ciertos tipos: números, cadenas, matrices/listas, objetos/dictos. Los objetos son solo mapas de clave = valor y los Arrays son listas ordenadas.

Así que no hay forma de expresar objetos personalizados de forma genérica. La solución es definir una estructura en la que su (s) programa (s) sabrán que es un objeto personalizado.

He aquí un ejemplo:

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

Esto podría ser utilizado para crear una instancia de MyClass y establecer los campos a y foo a 123 y "bar".

+4

Esto puede ser cierto, pero la pregunta no es sobre representación objetos de una manera genérica. Parece que tiene una bolsa JSON específica que se asigna a una clase específica en uno o ambos extremos. No hay ninguna razón por la que no pueda usar JSON como una serialización explícita de clases con nombre no genérico de esta manera. Nombrarlo como lo hace está bien si quiere una solución genérica, pero tampoco tiene nada de malo tener un contrato acordado en la estructura JSON. – DougW

20

Puedes hacerlo - es un kludge pero totalmente posible. Tuvimos que hacer cuando comenzamos a almacenar cosas en couchbase.

$stdobj = json_decode($json_encoded_myClassInstance); //JSON to stdClass 
$temp = serialize($stdobj);     //stdClass to serialized 

// Ahora que meter la mano y cambiar la clase del objeto serializado

$temp = preg_replace('@^O:8:"stdClass":@','O:7:"MyClass":',$temp); 

// unserialize y camina lejos como nada sucedió

$myClassInstance = unserialize($temp); // Presto a php Class 

En nuestros puntos de referencia de esta manera era más rápido que tratar de iterar a través de todas las variables de clase.

Advertencia: No funciona para los objetos anidados que no sean stdClass

Editar: tener en cuenta la fuente de datos, se recomienda encarecidamente que no lo hace de aparentes datos no confiables de los usuarios sin un análisis muy carful de los riesgos.

+0

Funciona esto con subclases encapsuladas. P.ej. '' '{" a ": {" b ":" c "}}' '', donde el objeto en 'a' es de otra clase y no solo una matriz asociativa? –

+1

no, json_decode crea objetos stdclass, incluidos subobjetos, si desea que sean otra cosa, debe modificar cada objeto como se indica anteriormente. –

+0

Gracias, eso es lo que imaginé –

14

Creamos JsonMapper para asignar objetos JSON en nuestras propias clases de modelo automáticamente. Funciona bien con objetos anidados/secundarios.

Sólo se basa en información de bloque de documentación tipo para mapeo, que la mayoría de las propiedades de la clase tienen todos modos:

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

muchos gracias por su gran biblioteca. –

+0

¡GUAU! Eso es simplemente increíble. – vothaison

5

Usted podría utilizar J ohannes Schmitt's Serializer library.

$serializer = JMS\Serializer\SerializerBuilder::create()->build(); 
$object = $serializer->deserialize($jsonData, 'MyNamespace\MyObject', 'json'); 
0

Una vez creé una clase base abstracta para este propósito. Vamos a llamarlo JsonConvertible. Debe serializar y deserializar a los miembros públicos. Esto es posible usando Reflection y binding estático tardío.

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

Solo de memoria, probablemente no sea perfecto. También deberá excluir las propiedades estáticas y puede dar a las clases derivadas la posibilidad de ignorar algunas propiedades cuando se serializan en/desde json. Espero que entiendas la idea, sin embargo.

0

Puede hacerlo en muy por debajo ..

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

?>

Para más detalles visita create-custom-class-in-php-from-json-or-array

0

Usted puede hacer un contenedor para el objeto y hacer que la envoltura se parece es el objeto mismo. Y funcionará con objetos multinivel.

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