I'm new to Ruby
and having a little trouble json
. I have inherited my classes with custom made JSONable
class, as explained HERE in this answer. 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. so i call to_json
on request
object as:
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.
(gives error: in 'to_json': wrong number of arguments (1 for 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. 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. 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. JSON validator also fails to validate this result, i checked online
Questions:
How can I avoid this, and produce valid JSON in this case?
How can I apply generic check to in my JSONable class to check if the object is of some custom class / complex object.
(currently i have checked only for specific classes as:)
if((self.instance_variable_get var).instance_of? Options ||((varVal).instance_of? Search))
Other Info:
- It works fine for all complex objects, having no nested objects
- API is developed in .NET
- I'm not using Rails, its a Ruby console app (I'm new to Ruby)