I am trying to create a group of map markers with the results of to_gmaps4rails
in an each
block. On an array with valid geo coordinates the to_gmaps4rails
method produces valid JSON.
I'm using Mongoid and my geo coordinates are in a sub-collection like so:
Account.locations.coordinates
Here is my controller code. nearby_sales
is a collection of Accounts
:
@json = String.new
nearby_sales.each do |sale|
@json << sale.locations.to_gmaps4rails
end
The browser complains about my @json
not being well-formed.
Is there a Ruby way to append valid JSON together?
JSONObject to merge two JSON objects in Java. We can merge two JSON objects using the putAll() method (inherited from interface java. util.
Arrays in JSON are almost the same as arrays in JavaScript. In JSON, array values must be of type string, number, object, array, boolean or null. In JavaScript, array values can be all of the above, plus any other valid JavaScript expression, including functions, dates, and undefined.
The file is invalid if it contains more than one JSON object. When you try to load and parse a JSON file with multiple JSON objects, each line contains valid JSON, but as a whole, it is not a valid JSON as there is no top-level list or object definition.
You can't concatenate JSON formatted strings returned by to_gmaps4rails
because they won't result in a valid object once decoded.
If I have some objects I want to send:
loc1 = {"longitude" => "2.13012", "latitude" => "48.8014"}
loc2 = {"longitude" => "-90.556", "latitude" => "41.0634"}
And convert them to JSON like to_gmaps4rails
does:
loc1_json = loc1.to_json
=> "{\"longitude\":\"2.13012\",\"latitude\":\"48.8014\"}"
loc2_json = loc2.to_json
=> "{\"longitude\":\"-90.556\",\"latitude\":\"41.0634\"}"
They're two JSON-encoded objects as strings.
Concatenate the resulting strings:
loc1_json + loc2_json
=> "{\"longitude\":\"2.13012\",\"latitude\":\"48.8014\"}{\"longitude\":\"-90.556\",\"latitude\":\"41.0634\"}"
And send them to another app with a JSON decoder, I'll get:
JSON[loc1_json + loc2_json]
JSON::ParserError: 743: unexpected token at '{"longitude":"-90.556","latitude":"41.0634"}'
The parser only makes it through the string partway before it finds a closing delimiter and knows there's an error.
I can wrap them in an array or a hash, and then encode to JSON again, but that doesn't help because the individual JSON strings will have been encoded twice, and will need to be decoded twice again to get back the original data:
JSON[([loc1_json, loc2_json]).to_json]
=> ["{\"longitude\":\"2.13012\",\"latitude\":\"48.8014\"}",
"{\"longitude\":\"-90.556\",\"latitude\":\"41.0634\"}"]
JSON[([loc1_json, loc2_json]).to_json].map{ |s| JSON[s] }
=> [{"longitude"=>"2.13012", "latitude"=>"48.8014"},
{"longitude"=>"-90.556", "latitude"=>"41.0634"}]
It's not a situation a JSON decoder expects, so that'd require some funky JavaScript on the client side to use the magic JSON decoder-ring twice.
The real solution is to decode them back to their native Ruby objects first, then re-encode them into the array or hash, then send them:
array_of_json = [loc1_json, loc2_json].map{ |s| JSON[s] }.to_json
=> "[{\"longitude\":\"2.13012\",\"latitude\":\"48.8014\"},{\"longitude\":\"-90.556\",\"latitude\":\"41.0634\"}]"
The values are correctly encoded now and can be sent to the destination browser or app, which can then make sense of the resulting data, not as an array of strings as above, but as an array of hashes of data:
JSON[array_of_json]
=> [{"longitude"=>"2.13012", "latitude"=>"48.8014"},
{"longitude"=>"-90.556", "latitude"=>"41.0634"}]
loc1 == JSON[array_of_json][0]
=> true
loc2 == JSON[array_of_json][1]
=> true
Applying that to your code, here's what needs to be done:
@json = []
nearby_sales.each do |sale|
@json << JSON[sale.locations.to_gmaps4rails]
end
@json.to_json
This decodes the locations back to their "pre-JSON" state, appends them to the array, then returns the array in JSON format.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With