8
votes

Comment faire la sérialisation de l'objet rubis à l'aide de JSON

J'ai une structure de classes de conteneurs simples comme (à Pseudo Ruby):

class A
  attr_reader :string_field1, :string_field2
  ...
end

class B
  attr_reader: int_field3, :string_field4
  ...
end

# C includes an instance of A and B
class C
  attr_reader: :a_instance, :b_instance
  ...
end


0 commentaires

3 Réponses :


6
votes

Utilisez le maréchal, le PSTORE ou une autre solution de rubis pour les objets non-JSON

On pourrait raisonnablement se demander pourquoi un langage complètement réfléchissant comme Ruby n'attune pas la génération du JSON et l'analyse de classes arbitraires. P>

Toutefois, à moins que vous n'obtenez aux types JSON, il n'ya aucun endroit où envoyer ou recevoir les objets JSON sauf à un autre Ruby en cours d'exécution. Et dans ce cas, je soupçonne que la sagesse conventionnelle est "Oublie Json, utilise une interface de rubis native comme la classe principale maréchal code>. P>

donc, si vous envoyez vraiment ces objets à PHP ou quelque chose de non-rubis, vous devez créer directement des structures de données Ruby pris en charge par JSON à l'aide de la matrice, puis vous aurez quelque chose que JSON.Generate versera directement. P>

Si vous venez de Besoin de sérialisation Il est possible que vous puissiez utiliser marshal code> ou pstore code>. p>

mise à jour: aha, ok, essayez ceci: p> xxx

si vous inclure Autoj code> dans chacune de vos classes, il devrait être DTRT. Dans votre exemple, il en résulte P>

[
  ["aa", "bb"],
  [123, "dd"]
]


2 commentaires

Merci, voyez ma clarification. Je était sous l'impression qu'il serait un peu plus automatique qu'aujourd'hui.


Soyez juste prudent avec les fermetures de maréchalage, comme lambdas ou Procs . Ils ne peuvent pas. Je ne sais pas si c'est une liste étendue, peut-être que d'autres structures ne peuvent aussi être barégées.



2
votes

J'ai eu le même problème (essaie principalement de créer des cordes JSON de complexité arbitraire) plutôt que de les analyser. Après avoir regardé partout pour une classe non invasive qui prendra un objet rubis (y compris des tableaux imbriqués) et le maréchal en tant que chaîne JSON, j'ai enfin écrit mon propre sérieliseur simple. Ce code échappe également à des caractères spéciaux pour créer JSON valide.

http://www.keepingmyhandin.com / Downhome / Sketchup / SimpleJsonserializerrubyImplementation P>

Tout ce que vous avez à faire est: P>

json  = JSON.new;
jsonString = json.marshal(obj); # Where obj is a Ruby object


0 commentaires

1
votes

Voici mon approche de to_json code> implémentation des classes personnalisées.

Il y a une petite magie ici utilisant auto-self. / code> dans un module. Voici un très bel article de 2006 sur le module ayant à la fois des méthodes d'instance et de classe http://blog.jayfields.com/2006/12/Ruby-Instance-and-Class-Methods-de-from.html P>

Le module est conçu pour être conçu pour être conçu pour être Inclus dans n'importe quelle classe pour fournir to_json code> fonctionnalité. Il intercepte attr_accessor code> méthode plutôt que d'utiliser son propre afin de nécessiter des modifications minimales pour les classes existantes. P>

to_json code> est basé sur ce answer p>

module JSONable
  module ClassMethods
    attr_accessor :attributes

    def attr_accessor *attrs
      self.attributes = Array attrs
      super
    end
  end

  def self.included(base)
    base.extend(ClassMethods)
  end

  def as_json options = {}
    serialized = Hash.new
    self.class.attributes.each do |attribute|
      serialized[attribute] = self.public_send attribute
    end
    serialized
  end

  def to_json *a
    as_json.to_json *a
  end
end


class CustomClass
  include JSONable
  attr_accessor :b, :c 

  def initialize b: nil, c: nil
    self.b, self.c = b, c
  end
end

a = CustomClass.new(b: "q", c: 23)
puts JSON.pretty_generate a

{
  "b": "q",
  "c": 23
}


0 commentaires