I am creating a client for a REST API that returns JSON like so:
2.1.5 :006 > system = api.system
=> {"DatabaseVersion"=>5, "Name"=>"Orthanc", "Version"=>"0.8.6"}
I'm wondering if there is a way to convert those JSON keys into methods so I could call something like
version = api.system.version
And would get the value of that JSON key:
=> "0.8.6"
Obviously I could hardcode each JSON item key as a method in the client, retrieving the value of a specific key with something like:
api.system["Version"]
But I'm wondering if this can be done programatically for each key/value that is received, without previous knowledge of the keys/values to be returned
OpenStruct
comes to the rescue:
▶ os = OpenStruct.new({
▷ "DatabaseVersion"=>5,
▷ "Name"=>"Orthanc",
▷ "Version"=>"0.8.6"
▷ })
▶ os.DatabaseVersion
#⇒ 5
edit :
As @mudasobwa pointed out, there is already a standard implementation, with a class that uses method_missing
and an inner Hash object...
Apparently this behavior is loved by many and found it's way to the standard library.
see the documentation on OpenStruct .
remember to require the implementation using: require 'ostruct'
original post :
I think you might be looking for a solution based on method_missing
.
It's possible to monkey patch the Hash class for a behavior that will mimic what you want.
Here's a quick dirty patch:
class Hash
def method_missing(name, *args, &block)
# getter for symbole
return self[name] if self.has_key? name
# getter for String
return self[name.to_s] if self.has_key? name.to_s
# setter for adding or editing hash keys,
# using the shortcut hash.key = value.
if name.to_s[-1] == '=' && name.to_s.length > 1
self.[]=(name.to_s[0..-2], *args)
self.[]=(name.to_s[0..-2].to_sym, *args)
return *args
end
# nothing happened? move it up the chain for default behavior.
# (assumes Hash doesn't handle missing methods).
super
end
end
This will behave like an 'on the fly' getter and setter. Notice the getter will work only for existing properties and that numbers are not supported (only Strings and symbols).
Also notice that symbols and strings will be unified - if will not be possible to use a symbol and a string for different values using these getter/setters. Also, symbols will have priority.
Personally, I would probably forgo such a solution of convenience or opt to sub-classing the Hash class. I'm not too comfortable with monkey patches.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.