1

My JSON array is structured like this:

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

In the ruby program, I am wanting to be able to edit the lat and long values for the names. But I am not quite sure how to do so.

sections.each do |user_coords|
        user_coords.each do |user, coords|
            if user == Usrname then
                #Change lat and long value for Usrname
            end
        end
end

How can this be done?

1
  • You really need to look into why your hash is so convoluted. A normally defined hash would be much easier to navigate/modify. As is, you're working on something you'll rarely see, so the things you learn to work with this one will not apply to normal hashes. Just something to think about. Commented Apr 3, 2014 at 20:25

2 Answers 2

2

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.

Sign up to request clarification or add additional context in comments.

2 Comments

I have now changed the JSON script to this: {"data":{"Chris":{"long":10,"lat":10},"Scott":{"long":9,"lat":18}}} How can I add another person called Bob with long = 10 and lat = 20
You really need to read through some Ruby tutorials. This is basic Hash Usage 101.
1
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}]}...]'

4 Comments

Why did you comment part of the last line out?
The last line is showing you the value being returned. It's a feature in the TextMate and Sublime text editors used by many developers and similar to the output you'd see in IRB.
@Cj1m: it's a common practice when sharing code examples with others to demonstrate a statement along with a comment displaying the return value (statement # => return value). For example, in JavaScript you might say [1,2,3].pop(); // => 3.
I then want to add sections back into the "data" array, how can I do that?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.