2011-10-27 38 views
6

Hice una pregunta previa sobre serialización y validación. Alguien mencionó el uso de la gema JSON que me permite decirle a mi objeto cómo serializar con el método to_json, sin embargo, Ruby parece hacer MUCHAS cosas complicadas con mucha facilidad, sin embargo por el otro lado algunas cosas realmente simples parecen ser bastante complicadas, la Serialización es una de esas cosas¿Serializar un objeto a JSON, XML, YAML?

quiero saber si hay una manera de tener un objeto limpio:

class CleanClass 
    attr_accessor :variable1 
    attr_accessor :variable2 
    attr_accessor :variable3 
end 

cleanObject = CleanClass.new 

Idealmente, yo no quiero ensuciar el modelo, sólo quiero pasarlo a algo y dígale cuál debe ser el tipo de salida y deje que funcione su magia.

Un ejemplo sería algo así como:

jsonOutput = MagicSerializer::Json.Serialize(cleanObject) 
xmlOutput = MagicSerializer::Xml.Serialize(cleanObject) 
yamlOutput = MagicSerializer::Yaml.Serialize(cleanObject) 

revertedJsonObject = MagicSerializer::Json.Unserialize(jsonOutput) 
revertedXmlObject = MagicSerializer::Xml.Unserialize(xmlOutput) 
revertedYamlObject = MagicSerializer::Yaml.Unserialize(yamlOutput) 

Quiero pasar algo de un objeto, y obtener las cadenas emiten, a continuación, ser capaz de convertir de nuevo.

Sé que ActiveModel tiene funcionalidad de serialización pero necesito ensuciar mi clase para hacer esto, y no quiero cambiar el modelo si es posible. ActiveSupport parece satisfacer los criterios JSON ya que puedo llamarlo y tomará un objeto y escupirá el JSON, pero me gustaría apoyar otros tipos.

¡Cualquier información adicional sería genial!

+0

'JSON.dump (objeto)' y 'JSON.parse (cadena) ' – Kris

Respuesta

11

Ruby tiene una función de serialización/deserialización automotriz a binario y yaml.

Yaml:

require 'yaml' 
serialized = CleanClass.new.to_yaml 
object = YAML.load(serialized) 

Mariscal:

serialized = Marshal.dump(CleanClass.new) 
object = Marshal.load(serialized) 
+0

Sí, he visto esto, pero Json es más importante actualmente para mí, luego Xml, luego Yaml. Así que esperaba que hubiera una gema o biblioteca que hiciera todo desde una interfaz simplificada. – Grofit

+1

El formato JSON es demasiado limitado para capturar el estado de un objeto ruby ​​completo. Solo tiene primitivos, por lo que necesitaría personalizar su JSON para incluir información de tipo de las variables de instancia. Además, si el objetivo es la serialización para que el objeto pueda leerse en otro lugar, es probable que deba adherirse a una API. Se podría decir que la responsabilidad de una clase es convertirse a un formato externo, y volver a leer ese formato. – Ewout

+0

Como dije en la respuesta a Dave anterior, no veo por qué necesitas decirle a ruby ​​cómo serializar estas clases (usando las suposiciones encima). Todo lo que realmente necesitan es un método recursivo para ir a través de cada instancia de un objeto, hasta que lleguen a otro objeto, luego bajen más al árbol, estoy seguro de que todos los objetos terminan como un modelo de tipos simples al final. La única vez que pude ver que el usuario necesita ingresar cualquier lógica de serialización es si quieren cambiar el nombre de las claves, es decir, attr_accessor: Apellido a ser serializado a apellido o algo similar. – Grofit

1

Para JSON y YAML Parece bastante fácil, ya que sólo serían las envolturas de los métodos to_yaml y to_json (o YAML.load y from_json respectivamente)

Para JSON que tendría que envolver clases propias alrededor del núcleo-Tipos (u otros tipos que implementan to_json), por ejemplo primero implemente un método to_hash que luego se puede transformar en json.

XML es mucho más complicado debido al aspecto de jerarquía, tendría que estandarizarlo, pero en realidad no entiendo de su explicación lo que está mal con los métodos básicos to_.... Esta es realmente la convención que usamos en Ruby. Si le preocupa la contaminación de los modelos, puede poner estos métodos en un módulo e incluir el módulo en la clase.

module Foo 
    def to_serialized_type 
    ... 
    end 
end 
class CleanClass 
    include Foo 
end 
+0

Cuando intenta usar to_xxxx con una instancia de una de sus propias clases, debe escribir un método to_xxxx dentro de su clase para indicarle cómo serializar (según lo que he leído actualmente, o sale como # <9135f3> en lugar de {something: blah}). Ese es el problema que no quiero tener para contaminar el modelo con preocupaciones de serialización. – Grofit

+0

no lo llamaría contaminante, ya que esa es la forma en que normalmente trabajas en ruby: directamente en el objeto en lugar de funcionalmente – robustus

1

Haga que su método de serialización magia sucia del objeto para usted; el emdirtering puede ocurrir por objeto.

O sucio en su nivel de clase.

De cualquier manera, su código de línea principal no lo ve.

+0

¿Podría dar más detalles, sé que puede agregar a las clases después de la declaración, que es quizás lo que quiere decir.Sin embargo, incluso si escribí algún código fuera de esa clase para decirle cómo serializar, eso es más código que tengo que mantener dentro de mi proyecto, y tendría que escribirse por tipo de clase. es decir, si una clase Persona tiene un primer nombre y un apellido, entonces una clase comercial tiene campos de nombre y dirección, entonces tendría que escribir 2 bits separados de lógica de serialización para tratar con ellos, con gráficos de objetos complejos que comenzarían a perderse. – Grofit

+0

El código de serialización existente no especifica cómo escribir un objeto, al menos para propiedades simples, interroga al objeto. Si tiene necesidades complejas de serialización, tendrá que indicarle cómo/en algún lugar /. Básicamente, estás pidiendo dos cosas: quiero tener el control completo de cómo se serializó mi clase, pero no quiero esa información en mi clase, y quiero que se maneje automáticamente. No funciona así; debe definir cómo se serializará/en algún lugar /. –

+0

Permítanme aclarar, no estoy pidiendo el control completo de cómo se serializa mi clase. Solo quiero que sea serializado, se pueden hacer las siguientes suposiciones de cualquier clase que se serialice automáticamente sin ningún esfuerzo por parte de los usuarios. Solo los campos/variables públicamente accesibles se serializan, y se utilizan como un par de valores clave A MENOS que el valor sea de otra clase, en el que se utiliza la recursividad para seguir descendiendo hasta que todos los tipos simples se hayan serializado. Creo que son suposiciones justas y (aunque no conozco tan bien a Ruby) deberían ser fáciles de acceder. – Grofit