[英]Custom to_json for nested complex objects in Ruby
I'm new to Ruby
and having a little trouble json
. 我是Ruby
新手,但json
有点麻烦。 I have inherited my classes with custom made JSONable
class, as explained HERE in this answer . 我已经用自定义的JSONable
类继承了我的类,如本答案所述 。 I have customized it according to my need, but I couldn't figure out how to make it work with custom nested (complex) objects, according to my requirement. 我已经根据需要对它进行了自定义,但是我无法根据自己的需求弄清楚如何使其与自定义嵌套(复杂)对象一起使用。 I have following scenario. 我有以下情况。
First Class: 头等舱:
class Option < JSONable
def IncludeAll=(includeAll) #bool
@includeAll = includeAll
end
def IncludeAddress=(includeAddress) #bool
@includeAddress= includeAddress
end
......
Second Class: 二等舱:
class Search < JSONable
def CustomerId=(customerId)
@customerId = customerId
end
def identifier=(identifier)
@identifier = identifier
end
def Options=(options) #This is expected to be of Class Option, declared above
@options = options
end
Third Class: 第三类:
class Request < JSONable
def DateTimeStamp=(dateTimeStamp)
@dateTimeStamp = dateTimeStamp
end
def SDKVersion=(sDKVersion)
@sDKVersion = sDKVersion
end
def RequestMessage=(requestMessage) #This is of type Search, declared above
@requestMessage = requestMessage
end
I call it as: 我称其为:
search = Search.new
searchOpts = Options.new
request = Request.new
search.identifier = identifier
searchOpts.IncludeAll = false
searchOpts.IncludeAddress = true
search.Options = searchOpts #setting nested level2 property here
//THE MOST OUTER CLASS OBJECT
request.SDKVersion = "xyz"
request.RequestMessage = search #setting nested level1
My ultimate goal is to send this request
object to an API
, after converting it to JSON. 我的最终目标是将request
对象转换为JSON之后,将其发送到API
。 so i call to_json
on request
object as: 所以我在request
对象上调用to_json
为:
request.to_json
But here, suggested solution in that post (JSONable) fails in this case, as it can't convert the nested complex objects request.search
and request.search.Options
to Json. 但是这里,该帖子中的建议解决方案(JSONable)在这种情况下失败了,因为它无法将嵌套的复杂对象request.search
和request.search.Options
转换为Json。
(gives error: in 'to_json': wrong number of arguments (1 for 0) (ArgumentError)') (给出错误:在'to_json'中:错误的参数数量(1代表0)(ArgumentError)')
What I tried: 我试过的
class JSONable
def to_json
hash = {}
self.instance_variables.each do |var|
#hash[var] = self.instance_variable_get var #tried to apply following check
if((self.instance_variable_get var).instance_of? Options ||((varVal).instance_of? Search))
varVal = self.instance_variable_get var
hash[var] = varVal.to_json #convert inner object to json
else
hash[var] = self.instance_variable_get var
end
end
hash.to_json
end
.....
This converts the nested model without any problem, but it messes up the 3rd level json. 这样可以毫无问题地转换嵌套模型,但是会弄乱3级json。 The result is as following: 结果如下:
{"DateTimeStamp":"121212","SDKVersion":"1.5","Culture":"en","RequestMessage":"{\"identifier\":\"851848913\",\"Options\":\"{\\\"IncludeAll\\\":true,\\\"IncludeAssociatedEntities\\\":true,\\\"IncludeAddress\\\":true,\\\"IncludePaymentInstructions\\\":true}\"}"}
And API doesn't respond. 而且API没有响应。 It seems as it messes up the boolean variables, which should be something like: 似乎弄乱了布尔变量,应该是这样的:
"SearchOption":"{\\"IncludeAll\\":true,\\"IncludeAssociatedEntities\\":true,\\...
but it gives: 但它给出:
"SearchOption\\":\\"{\\\\\\"IncludeAll\\\\\\":true,\\\\\\"IncludeAssociatedEntities\\\\\\":true,\\\\\\"Includ...
So the API logic can't cast it to corresponding bool
objects anymore. 因此,API逻辑无法将其bool
为相应的bool
对象。 JSON validator also fails to validate this result, i checked online 我在线检查了JSON验证程序也无法验证此结果
Questions: 问题:
How can I avoid this, and produce valid JSON in this case? 如何避免这种情况,并在这种情况下产生有效的JSON?
How can I apply generic check to in my JSONable class to check if the object is of some custom class / complex object. 如何在我的JSONable类中应用泛型检查,以检查对象是否属于某些自定义类/复杂对象。
(currently i have checked only for specific classes as:) (目前,我只检查了以下特定课程:)
if((self.instance_variable_get var).instance_of? Options ||((varVal).instance_of? Search))
Other Info: 其他资讯:
The answer you referred is dated “Dec 2010.” JSON
library is included in ruby stdlib for years already and it perfectly converts Hash
instances to json. 您提到的答案的日期为“ 2010年12月” JSON
库已包含在ruby stdlib中已有数年之久,并且可以完美地将Hash
实例转换为json。 That said, you just need to construct hashes out of your objects and then call JSON.dump
on the resulting hash. 就是说,您只需JSON.dump
对象中构造哈希,然后在生成的哈希上调用JSON.dump
。 I have no idea what JSONable
is and you definitely do not need it. 我不知道什么是JSONable
,您肯定不需要它。 Introduce some base class, let's call it Base
: 介绍一些基类,我们称它为Base
:
class Base
def to_h
instance_variables.map do |iv|
value = instance_variable_get(:"@#{iv}")
[
iv.to_s[1..-1], # name without leading `@`
case value
when Base then value.to_h # Base instance? convert deeply
when Array # Array? convert elements
value.map do |e|
e.respond_to?(:to_h) ? e.to_h : e
end
else value # seems to be non-convertable, put as is
end
]
end.to_h
end
end
Now just derive your classes from Base
to make them respond to to_h
, define all your instance variables as you did, and call: 现在,仅从Base
派生您的类以使它们响应to_h
,像您一样定义所有实例变量,然后调用:
require 'json'
JSON.dump request.to_h # request.to_h.to_json should work as well
The above should produce the nested JSON, hashes are happily converted to json by this library automagically. 上面的代码应该生成嵌套的JSON,此库会自动将哈希值愉快地转换为json。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.