2010-09-16 57 views
5

我試圖修改內置時間戳格式的默認反序列化,以影響Ruby的時間。Ruby YAML :: load

我這樣做(成功)與哈希:

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 

但是,當我嘗試用時間相同,這是行不通的:

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' 

任何幫助,將不勝感激。謝謝!

+0

我不知道,如果是相關的,但YAML未能根據http://redmine.ruby-lang.org/issues/show/4005 – 2010-11-30 07:01:31

+0

到往返時間對象第一行的目的是什麼,'YAML :: add_domain_type('yaml.org,2002','map'){| t,v | nil}',因爲如果你刪除它,哈希也不起作用。 – stephenr 2010-09-19 16:46:39

+0

[YAML :: add_domain_type]的引用(http://yaml4r.sourceforge.net/doc/class/yaml_add_domain_type_method.htm)。 – 2012-10-18 18:12:39

回答

2

如果您使用Psych(在Ruby 1.9.3p194中爲YAML),那麼您需要在Time類中定義encode_with/1方法。

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!!" 

如果encode_with/1方法是在對象上定義然後精極度緊張調用方法傳入Psych::Coder類的一個實例;否則,它會調用YAMLTree類中的visit_#{o.class}方法,該類在visit_Time的情況下不會序列化任何標記信息。

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