默认情况下,将序列化为数组:
>> s = Set.new [1,2,3] >> s.to_json => "[1,3]"
在你尝试反序列化之前,这是很好的.
class Set def to_json(*a) { "json_class" => self.class.name,"data" => { "elements" => self.to_a } }.to_json(*a) end def self.json_create(o) new o["data"]["elements"] end end
哪个工作很好
>> s = Set.new [1,3] >> s.to_json => "{\"data\":{\"elements\":[1,3]},\"json_class\":\"Set\"}"
直到我把The Set放入哈希或其他东西:
>> a = { 'set' => s } >> a.to_json => "{\"set\":[1,3]}"
解决方法
你的问题是Rails这样做:
[Object,Array,FalseClass,Float,Hash,Integer,NilClass,String,TrueClass].each do |klass| klass.class_eval <<-RUBY,__FILE__,__LINE__ # Dumps object in JSON (JavaScript Object Notation). See www.json.org for more info. def to_json(options = nil) ActiveSupport::JSON.encode(self,options) end RUBY end
在active_support / core_ext / object / to_json.rb中.特别是,将Hash的to_json方法更改为ActiveSupport :: JSON.encode调用.
然后,看看ActiveSupport :: JSON :: Encoding :: Encoder,我们看到:
def encode(value,use_options = true) check_for_circular_references(value) do jsonified = use_options ? value.as_json(options_for(value)) : value.as_json jsonified.encode_json(self) end end
所以所有的Rails JSON编码都经过as_json.但是,您没有为Set定义自己的as_json,只是设置to_json并在Rails忽略它不使用的东西时变得困惑.
如果你设置自己的Set#as_json:
class Set def as_json(options = { }) { "json_class" => self.class.name,"data" => { "elements" => self.to_a } } end end
那么您将在Rails控制台和Rails中获得您的一切:
> require 'set' > s = Set.new([1,3]) > s.to_json => "{\"json_class\":\"Set\",\"data\":{\"elements\":[1,3]}}" > h = { :set => s } > h.to_json => "{\"set\":{\"json_class\":\"Set\",3]}}}"
请记住,as_json用于准备JSON序列化的对象,然后to_json生成实际的JSON字符串. as_json方法通常返回简单的可序列化数据结构,例如Hash和Array,并且在JSON中具有直接的类似性;那么,一旦你有一些像JSON这样的结构,那么to_json就被用来将其序列化成一个线性的JSON字符串.
当我们看标准的非Rails JSON库时,我们会看到如下所示的内容:
def to_json(*a) as_json.to_json(*a) end
猴子修补了基础课(符号,时间,日期,…).所以再次,to_json通常是以as_json来实现的.在这种环境中,我们需要包含标准的to_json以及上面的as_json for Set:
class Set def as_json(options = { }) { "json_class" => self.class.name,"data" => { "elements" => self.to_a } } end def to_json(*a) as_json.to_json(*a) end def self.json_create(o) new o["data"]["elements"] end end
并且我们将json_create类方法包含在解码器中.一旦这样做完全正确,我们在irb中得到这样的东西:
>> s = Set.new([1,3]) >> s.as_json => {"json_class"=>"Set","data"=>{"elements"=>[1,3]}} >> h = { :set => s } >> h.to_json => "{"set":{"json_class":"Set","data":{"elements":[1,3]}}}"
执行摘要:如果你在Rails,不用担心做任何事情to_json,as_json是你想玩的东西.如果你不在Rails中,在as_json中实现大部分的逻辑(尽管文档说明了),并添加了标准的to_json实现(def to_json(* a); as_json.to_json(* a); end).