2015-02-04 18 views
6

Sto provando a serializzare una semplice struct su JSON che funziona bene, ma non riesco a farlo per creare un'istanza di quella struct dal JSON. Ecco come sto cercando di farlo.Ruby serialize struct con JSON

require 'rubygems' 
require 'json' 

Person = Struct.new(:name, :age) 

json = Person.new('Adam', 19).to_json 
puts json 

me = JSON.load(json) 
puts me.name 

e ottengo il seguente output:

"#<struct Person name=\"Adam\", age=19>" 
/usr/lib/ruby/1.9.1/json/common.rb:148:in `parse': 746: unexpected token at '"#<struct Person name=\"Adam\", age=19>"' (JSON::ParserError) 
    from /usr/lib/ruby/1.9.1/json/common.rb:148:in `parse' 
    from /usr/lib/ruby/1.9.1/json/common.rb:309:in `load' 
    from why.rb:9:in `<main>' 

risposta

10

In questo caso, person.to_json non sta facendo quello che vi aspettate.

Quando si require 'json', la libreria JSON inserti un metodo #to_json su Object che è un ripiego se non c'è #to_json metodo specializzato fornito altrove. This inserted method equivale sostanzialmente a chiamare #to_s#to_json su un oggetto.

Nel caso del vostro Person classe qui, #to_s emette il standard Object#to_s, che, per impostazione predefinita, non fornisce una stringa leggibile dalla biblioteca JSON.

Tuttavia, Structfa fornire un metodo #to_h che può essere utilizzato per convertire tale struttura per una Hash, e Hash è (su richiede la libreria JSON) consapevoli di come generare un'uscita parseable JSON.

Così semplicemente cambiando:

json = Person.new('Adam', 19).to_json 
puts json 

a:

person = Person.new('Adam', 19) 
puts person.to_h.to_json 

farà quello che ci si aspetta.

(Per inciso, vorrei davvero raccomandare attuazione #to_json sulla classe Person direttamente come chiamare #to_h#to_json viola il Law of Demeter.)

+1

Grazie che ha funzionato perfettamente. Vorrei solo far notare a chiunque leggendo questo in futuro che il metodo to_h è stato aggiunto in ruby ​​2.0, quindi se stai usando 1.9.3 come lo dovevo aggiornare. –