2010-09-16 9 views
5

Sto tentando di modificare la deserializzazione predefinita del formato timestamp incorporato, per influenzare il tempo di Ruby.Ruby YAML :: carico

faccio questo (con successo) con Hash:

YAML::add_domain_type('yaml.org,2002', 'map') { |t, v| nil } 
YAML::add_domain_type('ruby.yaml.org,2002', 'hash') { |t, v| nil } 
hash = { :hello => :world } 
puts YAML::load(hash.to_yaml) # nil 

Ma quando provo lo stesso con Time, non funziona:

YAML::add_domain_type('yaml.org,2002', 'timestamp') { |t, v| nil } 
YAML::add_domain_type('ruby.yaml.org,2002', 'time') { |t, v| nil } 
puts YAML::load(Time.now.to_yaml).class # 'Time' 

Qualsiasi aiuto sarebbe apprezzato. Grazie!

+0

non sono sicuro se è legato, ma YAML non riesce a roundtrip oggetti tempo secondo http://redmine.ruby-lang.org/issues/show/4005 –

+0

qual è lo scopo della prima riga, 'YAML :: add_domain_type ('yaml.org, 2002', 'map') {| t, v | nil} 'perché se lo rimuovi, anche l'hash non funziona. – stephenr

+0

Riferimento per [YAML :: add_domain_type] (http://yaml4r.sourceforge.net/doc/class/yaml_add_domain_type_method.htm). –

risposta

2

Se si utilizza Psych (che è YAML in ruby ​​1.9.3p194), è necessario definire un metodo encode_with/1 nella classe Time.

require 'yaml' 

class Time 
    def encode_with(coder) 
    coder.tag = '!ruby/time' 
    coder.scalar = to_s 
    end 
end 

YAML::add_domain_type('ruby.yaml.org,2002', 'ruby/time') { |t, v| "HELLO!!" } 

yaml = YAML.dump(Time.new) # -> "--- !ruby/time 2012-10-25 14:18:59 -0400\n...\n" 
YAML.load(yaml) # -> "HELLO!!" 

Se il metodo encode_with/1 viene definita sull'oggetto allora Psych chiama tale metodo passando un'istanza della classe Psych::Coder; in caso contrario, chiama il metodo visit_#{o.class} nella classe YAMLTree, che nel caso di visit_Time non serializza alcuna informazione di tag.

https://github.com/tenderlove/psych/blob/master/lib/psych/visitors/yaml_tree.rb#l100-105

https://github.com/tenderlove/psych/blob/master/lib/psych/visitors/yaml_tree.rb#l172-175