2012-05-07 26 views
6

Quería serializar un objeto-gráfico completo de PHP a una representación de cadena JSON, y volver a serializarlo en un objeto-gráfico PHP idéntico.Serializar/deserializar objeto-gráfico PHP a JSON

Aquí se presenta un resumen de las opciones que consideré, y las razones por las que no trabajan para mí:

  • serialize() no hace lo que yo quiero, porque utiliza un formato específico para PHP. Quiero un formato que sea ampliamente compatible con la mayoría de los lenguajes, y legible por humanos/editable.

  • json_encode() no hace lo que quiero, porque solo hace valores simples y matrices, no objetos. (En realidad estoy usando esto en mi aplicación, véase más adelante.)

  • var_export() no maneja referencias circulares, y no hace lo que yo quiero (ver más arriba). (tenga en cuenta que mi aplicación actual no lo hace manejan las referencias circulares o bien - ver los comentarios y la respuesta por debajo de aclaración de este tema)

  • Sebastian Bergmann Object Freezer es una buena aplicación, pero no hace lo que yo quiero, ya sea -. se utiliza una forma muy largo, y se basa en rellenar objetos serializados con GUID.

  • Serialized no hace lo que quiero - en realidad no realiza la serialización, analiza la salida de serialize() y produce una representación diferente, p. XML, pero no puede analizar esa representación. (También no apoyar JSON - XML ​​es forma muy largo, y no es lo que quiero.)

ahora tengo una aplicación de trabajo para compartir:

https://github.com/mindplay-dk/jsonfreeze

El JSON- representación del objeto-gráfica se parece a esto:

{ 
    "#type": "Order", 
    "orderNo": 123, 
    "lines": [{ 
     "#type": "OrderLine", 
     "item": "milk \"fuzz\"", 
     "amount": 3, 
     "options": null 
    }, { 
     "#type": "OrderLine", 
     "item": "cookies", 
     "amount": 7, 
     "options": { 
      "#type": "#hash", 
      "flavor": "chocolate", 
      "weight": "1\/2 lb" 
     } 
    }], 
    "paid": true 
} 

este enfoque está diseñado para trabajar para una pura agregada estructura de árbol - las referencias circulares no están permitidos, ni r múltiple eferencias a los mismos objetos. En otras palabras, esto no es de propósito general, como p. serialize() y unserialize() que funcionan para cualquier objeto-gráfico de PHP.

En mi initial approach usé una forma serializada que era esencialmente una lista de objetos base-0. El primer objeto en la lista (número 0) es la raíz del objeto-gráfico serializado, cualquier otro objeto se almacena en el orden en que se encuentran.

En la implementación actual, la representación JSON se asemeja a la estructura en árbol original en la medida en que esto es posible, lo que hace posible trabajar con la representación JSON de un objeto-gráfico en JavaScript. La única desviación es la propiedad #type magia (con el prefijo # para evitar la colisión con la propiedad-nombres) y el "tipo" #hash, utilizado para distinguir array hashes de tipo (almacenados como objetos JSON) a partir de matrices de tipo array regulares (almacena como JSON matrices).


Me marcho estas notas sobre la versión anterior aquí con fines históricos.

Las referencias circulares se manejan simplemente al no almacenar nunca objetos anidados dentro de la representación serializada de cada objeto; en su lugar, cualquier referencia de objeto se almacena como un objeto JSON con el índice de objeto, p. Ej. {"__oref":2} es una referencia al objeto con índice 2 en la lista de objetos.

Tengo un problema con las referencias de matriz en mi implementación: cuando var_dump() dentro del código que restaura las referencias a los objetos de la matriz, se rellenan, pero en algún punto la matriz se copia, y terminas con la copia vacía. He intentado colocar & caracteres en todas partes en el código, pero independientemente de dónde pase por referencia, el resultado final es una matriz vacía.

+0

No llamaría al formato de serialización de PHP como está documentado - [al menos dentro del código fuente] (http://lxr.php.net/opengrok) /xref/PHP_TRUNK/ext/standard/var.c#php_var_serialize_intern) - pero también de terceros. Entonces puedes usarlo – hakre

+0

puede estar documentado, pero PHP es la única plataforma/idioma que tiene una implementación de unserialize() - Prefiero JSON, que ya es compatible con todos los lenguajes principales. Y también es legible por humanos. –

+0

Puede convertir datos serializados en XML que se admite en todas partes. La [Biblioteca serializada] (https://github.com/ktomk/Serialized) hace esto. No debería ser tan difícil extenderlo con un dumper json por cierto. - entonces tal vez lo encuentres útil. – hakre

Respuesta

2

El guión terminado (publicado anteriormente) cumple con mis requisitos precisos:

  • Serialize y unserialize un agregado entero.

  • Tienen una representación JSON que se parece mucho a la estructura de datos original.

  • No contamine la estructura de datos con claves generadas dinámicamente u otros datos.

No maneja referencias circulares. Como se señala en un comment above, no hay una forma correcta de almacenar referencias circulares o referencias múltiples al mismo objeto, ya que todas son iguales. Al darme cuenta de esto, decidí que mi objeto-gráfico debe ser un árbol regular, y acepté esta limitación como "algo bueno".

actualización: la salida ahora se puede formatear con sangría, nuevas líneas y espacios en blanco - era importante para mí tener una representación legible por el ser humano (y amigable con el control de fuente) para mis propósitos. (El formato se puede habilitar o deshabilitar según sea necesario.)

0

No sé si esto es lo que buscas, pero si solo estás interesado en obtener propiedades públicas de un objeto, get_object_vars ($ obj) hará el truco.

<?php 

class foo { 
    public $fname = "John"; 
    public $sname = "Doe"; 
    private $status = null; 
    static $type = "person"; 


} 

$obj = new foo; 

print_r((get_object_vars($obj))); 

print json_encode(get_object_vars($obj)); 

?> 

seria:

Array ([fname] => John [Sname] => Doe)

{ "fname": "Juan", "PROVEEDOR": "Doe"}

El método anterior es inútil para acceder a referencias de funciones y variables privadas, pero es posible que pueda usar esto junto con más código para activar lo que desee.

Dinesh.

+0

Si miraste la implementación que publiqué, fui un poco más allá ... –