1

I have a web service that returns a json in the following format:

[
    {
        "key": "linux.ubuntu.ip",
        "value": "10.10.10.10"
    },
    {
        "key": "linux.ubuntu.hostname",
        "value": "stageubuntu"
    }
]

I have a ruby code that makes a call to this service and gets the json. Deep in this code, there is a variable configure of type Hashie::Mash.

I want to achieve this:

configure.linux.ubuntu.ip = 10.10.10.10 [Hashie::Mash]
configure.linux.ubuntu.hostname = stageubuntu [Hashie::Mash]

Could anybody tell me if it is possible to achieve this (w.r.t to the json output that I have)? If so, what is the best method to do it?

sawa
  • 165,429
  • 45
  • 277
  • 381
Var
  • 329
  • 5
  • 14
  • Use the json library. – sawa Apr 13 '16 at 08:15
  • @sawa I did refer to the following post: http://stackoverflow.com/questions/13897846/is-it-possible-to-convert-a-json-string-to-an-object, but the json structure that is mentioned in this example is different than what i have, any suggestions on how i could do this? – Var Apr 13 '16 at 08:17
  • Variables in Ruby do not have types (classes). You can just assign an object that has a certain type. – sawa Apr 13 '16 at 08:18
  • Yes, this can be done in a very tricky way, but why you need to do this? Is `configure['linux.ubuntu.ip'] = '10.10.10.10'` that bad? – Aetherus Apr 13 '16 at 08:19
  • If you know how to convert the json into a Ruby object, then your question should start from there without mention to json. No need to make the question complicated. – sawa Apr 13 '16 at 08:19
  • @Aetherus Tricky way is fine! – Var Apr 13 '16 at 08:23
  • @Aetherus I need to do this because i need to add the above key value pair in the existing "config" hashie – Var Apr 13 '16 at 18:31

1 Answers1

2

To get a JSON string to a Hashie::Mash object you can simply do:

require 'json'
require 'hashie'

json_str = '{ "foo": "bar" }'
ruby_hash = JSON.parse(json_str)
Hashie::Mash.new(ruby_hash)

For this specific problem, though not ideal (but we all have our unique use cases) you're needing to parse to an array, then extract the 'key's into nested Hashie::Mash objects of some unknown depth.

require 'json'
require 'hashie'

json_str = <<-JSON
  [
    {
      "key": "linux.ubuntu.ip",
      "value": "10.10.10.10"
    },
    {
      "key": "linux.ubuntu.hostname",
      "value": "stageubuntu"
    }
  ]
JSON

parsed_arr = JSON.parse(json_str)
#=> [{"key"=>"linux.ubuntu.ip", "value"=>"10.10.10.10"}, {"key"=>"linux.ubuntu.hostname", "value"=>"stageubuntu"}]

configure = parsed_arr.map do |parsed_hash|
  method_chain = parsed_hash['key'].split('.')
  init_value   = Hashie::Mash.new(method_chain.pop => parsed_hash['value'])

  method_chain.reverse.inject(init_value) do |ret_value, method_name|
    Hashie::Mash.new(method_name => ret_value)
  end
end.inject(:merge) # <-- hashie is allows you to perform a deep merge into a single object here.

# you can now do

configure.linux.ubuntu.ip = 10.10.10.10 [Hashie::Mash]
#=> "10.10.10.10"

configure.linux.ubuntu.hostname
#=> "stageubuntu"
Travis
  • 13,311
  • 4
  • 26
  • 40