如何在Ruby中将JSON对象附加在一起

Ste*_*eO7 9 ruby ruby-on-rails gmaps4rails

我正在尝试to_gmaps4rails使用each块中的结果创建一组地图标记.在具有有效地理坐标的数组上,该to_gmaps4rails方法生成有效的JSON.

我正在使用Mongoid,我的地理坐标位于子集合中,如下所示:

Account.locations.coordinates  
Run Code Online (Sandbox Code Playgroud)

这是我的控制器代码.nearby_sales是一个集合Accounts:

@json = String.new
nearby_sales.each do |sale|
  @json << sale.locations.to_gmaps4rails
end
Run Code Online (Sandbox Code Playgroud)

浏览器抱怨我的@json身体状况不佳.有没有Ruby方法将有效的JSON附加到一起?

the*_*Man 18

您无法连接返回的JSON格式字符串,to_gmaps4rails因为它们在解码后不会生成有效对象.

如果我有一些我想发送的对象:

loc1 = {"longitude" => "2.13012", "latitude" => "48.8014"}
loc2 = {"longitude" => "-90.556", "latitude" => "41.0634"}
Run Code Online (Sandbox Code Playgroud)

并将它们转换为JSON,如to_gmaps4rails:

loc1_json = loc1.to_json
=> "{\"longitude\":\"2.13012\",\"latitude\":\"48.8014\"}"
loc2_json = loc2.to_json
=> "{\"longitude\":\"-90.556\",\"latitude\":\"41.0634\"}"
Run Code Online (Sandbox Code Playgroud)

它们是两个JSON编码的对象作为字符串.

连接结果字符串:

loc1_json + loc2_json
=> "{\"longitude\":\"2.13012\",\"latitude\":\"48.8014\"}{\"longitude\":\"-90.556\",\"latitude\":\"41.0634\"}"
Run Code Online (Sandbox Code Playgroud)

并使用JSON解码器将它们发送到另一个应用程序,我会得到:

JSON[loc1_json + loc2_json]
JSON::ParserError: 743: unexpected token at '{"longitude":"-90.556","latitude":"41.0634"}'
Run Code Online (Sandbox Code Playgroud)

解析器只有在找到结束分隔符并且知道存在错误之前才通过字符串.

我可以将它们包装在数组或散列中,然后再次编码为JSON,但这没有用,因为单个JSON字符串将被编码两次,并且需要再次解码两次以获取原始数据:

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"}]
Run Code Online (Sandbox Code Playgroud)

这不是JSON解码器所期望的情况,因此需要在客户端使用一些时髦的JavaScript来使用魔术JSON解码器环两次.

真正的解决方案是首先将它们解码回原生Ruby对象,然后将它们重新编码为数组或散列,然后发送它们:

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\"}]"
Run Code Online (Sandbox Code Playgroud)

这些值现在已正确编码,可以发送到目标浏览器或应用程序,然后可以理解结果数据,而不是如上所示的字符串数组,而是作为数据哈希数组:

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
Run Code Online (Sandbox Code Playgroud)

将其应用于您的代码,以下是需要完成的工作:

@json = []
nearby_sales.each do |sale|
  @json << JSON[sale.locations.to_gmaps4rails]
end
@json.to_json
Run Code Online (Sandbox Code Playgroud)

这会将位置解码回其"pre-JSON"状态,将它们附加到数组,然后以JSON格式返回数组.