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?
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.
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}]}...]'