Editing JSON Array contents in Ruby

前端 未结 2 349
长情又很酷
长情又很酷 2021-01-24 07:54

My JSON array is structured like this:

{\"data\":[{\"Chris\":[{\"long\":10,\"lat\":19}]},{\"Scott\":[{\"long\":9,\"lat\":18}]}]}

In the ruby pr

相关标签:
2条回答
  • 2021-01-24 08:25

    This is how to access individual elements in your JSON:

    require 'json'
    
    foo = JSON['{"data":[{"Chris":[{"long":10,"lat":19}]},{"Scott":[{"long":9,"lat":18}]}]}']
    foo['data'][0]['Chris'][0]['long'] = 5
    foo['data'][0]['Chris'][0]['lat'] = 7
    foo # => {"data"=>[{"Chris"=>[{"long"=>5, "lat"=>7}]}, {"Scott"=>[{"long"=>9, "lat"=>18}]}]}
    

    You can simplify the path somewhat, by using a variable as a placeholder into the object:

    foo = JSON['{"data":[{"Chris":[{"long":10,"lat":19}]},{"Scott":[{"long":9,"lat":18}]}]}']
    chris = foo['data'][0]['Chris'][0]
    chris['long'] = 5
    chris['lat'] = 7
    foo # => {"data"=>[{"Chris"=>[{"long"=>5, "lat"=>7}]}, {"Scott"=>[{"long"=>9, "lat"=>18}]}]}
    

    chris points to the "Chris" hash, which is embedded inside the foo hash. Changes to the chris hash occur inside foo.

    If the hash was defined normally, it'd be more clean/clear and straightforward:

    foo = JSON['{"data":{"Chris":{"long":5,"lat":7},"Scott":{"long":9,"lat":18}}}']
    foo['data']['Chris']['long'] = 5
    foo['data']['Chris']['lat'] = 7
    foo # => {"data"=>{"Chris"=>{"long"=>5, "lat"=>7}, "Scott"=>{"long"=>9, "lat"=>18}}}
    

    foo is more clearly defined as:

    foo = {
      'data' => {
        'Chris' => {'long' => 5, 'lat' => 7},
        'Scott' => {'long' => 9, 'lat' => 18}
      }
    }
    

    Conditionally iterating over the hash to find a particular key/value pair looks like this with your hash:

    require 'json'
    
    foo = JSON['{"data":[{"Chris":[{"long":10,"lat":19}]},{"Scott":[{"long":9,"lat":18}]}]}']
    
    user_name = 'Chris'
    data = foo['data'].first
    data.first.each do |key, value|
      if key == user_name
        data[user_name].first['long'] = 5
        data[user_name].first['lat'] = 6
      end
    end
    
    foo # => {"data"=>[{"Chris"=>[{"long"=>5, "lat"=>6}]}, {"Scott"=>[{"long"=>9, "lat"=>18}]}]}
    

    Having to use first (or [0]) to get at hash elements has smell to it.

    Using a hash that is defined correctly results in code that looks like:

    foo = JSON['{"data":{"Chris":{"long":10,"lat":19},"Scott":{"long":9,"lat":18}}}']
    foo['data'].each do |key, value| 
      if key == user_name
        value['long'] = 5
        value['lat'] = 7
      end
    end
    foo # => {"data"=>{"Chris"=>{"long"=>5, "lat"=>7}, "Scott"=>{"long"=>9, "lat"=>18}}}
    

    How can I add another person called Bob with long = 10 and lat = 20

    It sounds like you don't have a good grasp of manipulating/accessing hashes, or how to convert to/from JSON. You'd do well to get those basics down.

    Don't start with JSON, instead, start with a Ruby hash:

    require 'json'
    
    foo = {
      "data" => {
        "Chris" => {
          "long" => 5, 
          "lat" => 7
        }, 
        "Scott" => {
          "long" => 9,
          "lat" => 18
        }
      }
    }
    

    Add to that any other hash elements you want:

    bob_hash = {'Bob' => {'long' => 10, 'lat' => 20}}
    foo['data'].merge!(bob_hash)
    

    merge! adds bob_hash to foo['data']. Then, tell the hash to output its JSON representation using to_json. It's a lot easier to work with familiar Ruby structures, and let Ruby do the heavy-lifting of converting to JSON, than it is to try to do string manipulation on an existing JSON string. If you have the JSON, then parse it and convert/modify the resulting Ruby object, then output the JSON again.

    puts foo.to_json
    # >> {"data":{"Chris":{"long":5,"lat":7},"Scott":{"long":9,"lat":18},"Bob":{"long":10,"lat":20}}}
    

    I'd recommend reading "How to convert JSON to a hash, search for and change a value" also, as it's a useful alternative for accessing values in the resulting hash.

    0 讨论(0)
  • 2021-01-24 08:41
    username = 'Chris'
    sections.each do |user_coords|
      user_coords.each do |user, coords|
        if user == username then
          coords.each do |lat_long|
            lat_long['lat']  = 123 # Your value here...
            lat_long['long'] = 456 # Your value here...
          end
        end
      end
    end
    sections.to_json # => '[{"Chris":[{"long":456,"lat":123}]}...]'
    
    0 讨论(0)
提交回复
热议问题