Serializar / deserializar objeto-gráfico PHP a JSON

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

Aquí hay un resumen de las opciones que consideré, y razones por las cuales no funcionan para mí:

  • serialize() no hace lo que yo quiero, porque usa 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 yo quiero, porque solo hace arreglos y valores simples, no objetos. (De hecho, estoy usando esto en mi implementación, ver más abajo).

  • var_export() no maneja las referencias circulares, y no hace lo que yo quiero (ver arriba) (tenga en cuenta que mi implementación actual tampoco maneja las referencias circulares; vea los comentarios y responda a continuación para aclarar este problema).

  • El Congelador de objetos de Sebastian Bergmann es una buena implementación, pero tampoco hace lo que yo quiero: utiliza una forma muy larga y se basa en rellenar objetos serializados con GUID.

  • Serialized no hace lo que yo quiero, en realidad no realiza la serialización, analiza el resultado de serialize() y produce una representación diferente, por ejemplo, XML, pero no puede analizar esa representación. (Tampoco es compatible con JSON – XML ​​es una forma muy larga, y no es lo que quiero).

Ahora tengo una implementación en funcionamiento para compartir:

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

La representación JSON del objeto-gráfico se ve así:

 { "#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 funcionar para un agregado de estructura de árbol puro: no se permiten referencias circulares ni referencias múltiples a los mismos objetos. En otras palabras, esto no es de propósito general como, por ejemplo serialize() y unserialize() qué función para cualquier objeto-gráfico de PHP.

En mi enfoque inicial utilicé 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 mágica (con el prefijo # para evitar la colisión con nombres de propiedad) y #hash “tipo”, que se usa para distinguir los valores hash de tipo de array (almacenados como objetos JSON) de los array normales de tipo array (almacenados) como matrices JSON).


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

Las referencias circulares se manejan simplemente al no almacenar nunca objetos nesteds dentro de la representación serializada de cada objeto; en su lugar, cualquier referencia a objeto se almacena como un objeto JSON con el índice de objeto; por ejemplo, {"__oref":2} es una referencia al objeto con el í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 a la matriz, se rellenan, pero en algún momento se copia la matriz y se termina 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.

El script terminado (publicado arriba) cumple con mis requisitos precisos:

  • Serializar y deserializar un agregado completo.

  • Tener una representación JSON que se asemeje 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ñaló en un comentario anterior, 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; para mí era importante contar con una representación legible por el ser humano (y amigable con el control de fuente). (El formato se puede habilitar o deshabilitar según sea necesario).

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.

  

Se producirá:

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

{“fname”: “John”, “sname”: “Doe”}

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

Dinesh.