2012-12-21 7 views
9

Próbuję utworzyć grupę znaczników mapy z wynikami to_gmaps4rails w bloku each. W tablicy z poprawnymi współrzędnymi geograficznymi metoda to_gmaps4rails generuje prawidłowy JSON.Jak dołączyć obiekty JSON do siebie w Ruby

Używam Mongoid i moje współrzędne geograficzne są w sub-kolekcji tak:

Account.locations.coordinates 

Oto mój kod kontrolera. nearby_sales jest zbiorem Accounts:

@json = String.new 
nearby_sales.each do |sale| 
    @json << sale.locations.to_gmaps4rails 
end 

Przeglądarka narzeka na mój @json nie jest dobrze uformowane. Czy istnieje sposób Ruby, aby dołączyć prawidłowy JSON razem?

+2

Nie chcesz tablicy? W przeciwnym razie byłby to obiekt json z rzędu bez przecinków i struktury otaczającej. –

Odpowiedz

18

Nie można złączyć JSON sformatowane ciągi zwracanych przez to_gmaps4rails ponieważ nie spowoduje ważnego obiektu raz dekodowany.

Jeśli mam jakieś obiekty chcę wysłać:

loc1 = {"longitude" => "2.13012", "latitude" => "48.8014"} 
loc2 = {"longitude" => "-90.556", "latitude" => "41.0634"} 

i konwertować je do formatu JSON jak to_gmaps4rails robi:

loc1_json = loc1.to_json 
=> "{\"longitude\":\"2.13012\",\"latitude\":\"48.8014\"}" 
loc2_json = loc2.to_json 
=> "{\"longitude\":\"-90.556\",\"latitude\":\"41.0634\"}" 

Są dwa obiekty JSON-zakodowane jako ciągi.

złączyć powstałe ciągi:

loc1_json + loc2_json 
=> "{\"longitude\":\"2.13012\",\"latitude\":\"48.8014\"}{\"longitude\":\"-90.556\",\"latitude\":\"41.0634\"}" 

i wysłać je do innej aplikacji z dekodera JSON, Wezmę:

JSON[loc1_json + loc2_json] 
JSON::ParserError: 743: unexpected token at '{"longitude":"-90.556","latitude":"41.0634"}' 

Parser czyni go jedynie poprzez ciąg partway przed nim znajduje separator zamykający i wie, że wystąpił błąd.

Mogę je opakować w tablicę lub hasz, a następnie ponownie kodować do JSON-a, ale to nie pomoże, ponieważ poszczególne ciągi JSON zostaną zakodowane dwukrotnie i będą musiały zostać dwukrotnie odkodowane, aby odzyskać oryginalne dane:

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"}] 

To nie jest sytuacja dekoder JSON spodziewa się, że tak, że wymaga trochę ostry JavaScript po stronie klienta do korzystania z dekodera JSON magiczny pierścień dwukrotnie.

Rzeczywisty roztwór do dekodowania ich z powrotem do ich natywnej Ruby obiektów, następnie ponownego zakodowania ich w tablicy albo mieszania, a następnie wysłać je:

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\"}]" 

Wartości są odpowiednio zakodowanego się i może być wysyłane do przeglądarki docelowego lub aplikacji, które mogą następnie sensu otrzymanych danych, a nie jako tablica łańcuchów jak powyżej, ale jako tablica skrótów danych:

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 

Stosując że do kodu, tutaj co należy zrobić:

@json = [] 
nearby_sales.each do |sale| 
    @json << JSON[sale.locations.to_gmaps4rails] 
end 
@json.to_json 

To dekoduje położenia z powrotem do ich stanu "pre-JSON", dołącza je do tablicy, a następnie zwraca tablicę w formacie JSON.

+0

Działa doskonale! Dziękuję za działający kod, ale przede wszystkim za świetne wyjaśnienie! – SteveO7

+0

Jedna sprawa Mam nadzieję, że możesz mi pomóc. Chociaż json jest teraz dobrze uformowany, zawiera tablice tablic skrótów. Podobnie jak [[{"lat": 39, "lng": - 104}, {"lat": 39, "lng": - 105}], [{"lat": 39, "lng": - 104,5]] tworzenie jednego poziomu zbyt głębokiego. Czy istnieje sposób dodawania raw haszy do @json wewnątrz bloku? – SteveO7

+0

Czekajcie ... Myślę, że to mam. Dodałem .flatten! do ostatniej linii, tak jak; @ json.flatten! .to_json i json zwrócone do przeglądarki wygląda na to, że tego oczekuję. Widziałem ostrzeżenia o użyciu spłaszczenia może spowodować nieoczekiwane wyniki, wszelkie porady na ten temat? – SteveO7

2
require 'json' 

@json = Array.new 
nearby_sales.each do |sale| 
    @json << sale.locations.to_gmaps4rails 
end 
@json.to_json