Greg
Greg

Reputation: 2609

Rails jBuilder from GeoJSON to make another json

I'm trying to take a series of GeoJSON Line Strings and put them on a map. My jBuilder and Rails controller combination is not producing correctly formatted json for putting on a web map. Here's the relevant code.

overview_data.json.builder

json.type "FeatureCollection"
json.features @segments do |street|
  if (street.extent_json) # only if item has a line drawn
    json.type "Feature"
    json.properties do
       json.title "Was #{street.prevName} before #{street.dateEarliest} and now is #{street.currentName} #{street.dateLatest})"
    end
    json.geometry do
       # json.type "LineString"
       json.coordinates street.extent_json
    end # json.geometry
  end  # if
end # json.features

overview_controller.rb

class OverviewController < ApplicationController
  def index
  end
  def overview_data
    @segments = Street.all
  end
end

street.extent_json as it appears in a web form and in the database (Postgres via pgAdmin)

    {"type":"LineString",
    "coordinates":[[-118.25712423772116,34.01007010760971],
                  [-118.25649456380442,34.01016443793837],
                  [-118.25584971702219,34.01016443793837],
                  [-118.25427932544667,34.0102021700405],
                  [-118.25213995141625,34.010227324765935]]}

Output as seen in http://localhost:3000/overview/overview_data.json. At present there are about ten items that have extent_json. Below are the first few:

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {
        "title": "Was 10th St.  before 1903 and now is part of E. 9th Place (21). 1908)"
      },
      "geometry": {
        "coordinates": "{\"type\":\"LineString\",\"coordinates\":[[-118.24982816353442,34.035546195508864],[-118.25104052200915,34.03663976724366]]}"
      }
    },
    {
      "type": "Feature",
      "properties": {
        "title": "Was 37th St before 1903 and now is part of E. 40th Place 1928)"
      },
      "geometry": {
        "coordinates": "{\"type\":\"LineString\",\"coordinates\":[[-118.25712423772116,34.01007010760971],[-118.25649456380442,34.01016443793837],[-118.25584971702219,34.01016443793837],[-118.25427932544667,34.0102021700405],[-118.25213995141625,34.010227324765935]]}"
      }
    },
    {
      "type": "Feature",
      "properties": {
        "title": "Was Brook before 1903 and now is part of S. Toluca St. (26). and second block south gone 1908)"
      },
      "geometry": {
        "coordinates": "{\"type\":\"LineString\",\"coordinates\":[[-118.25862396508458,34.06087254304104],[-118.25933206826451,34.05994816216629]]}"
      }
    },
    {
      "type": "Feature",
      "properties": {
        "title": "Was Auto Pl before 1928 and now is Commonwealth Pl and a portion abandoned 1930)"
      },
      "geometry": {
        "coordinates": "{\"type\":\"LineString\",\"coordinates\":[[-118.28558737412096,34.07543021182353],[-118.28369373455645,34.07646106299854]]}"
      }
    },
    {
      "type": "Feature",
      "properties": {
        "title": "Was 3rd St before 1921 and now is Miramar St. One block abandoned )"
      },
      "geometry": {
        "coordinates": "{\"type\":\"LineString\",\"coordinates\":[[-118.26117539280003,34.05901974362122],[-118.2593849946753,34.05823410691563],[-118.25815599257271,34.05768101430694],[-118.25759459655055,34.05717191451128],[-118.25663111959356,34.05654339202722]]}"
      }
    },
    {
      "type": "Feature",
      "properties": {
        "title": "Was Gregory Way before  and now is Gregory Way 2017)"
      },
      "geometry": {
        "coordinates": "{\"type\":\"LineString\",\"coordinates\":[[-118.37295765057208,34.06188579510917],[-118.37272698059681,34.06172580874592],[-118.37264114990832,34.06161026285129],[-118.3725660480559,34.06146805230318],[-118.37253386154772,34.061414723286084],[-118.37249631062151,34.06118363049104]]}"
      }
    },

The problem is the added "{\"type\":\"LineString\",\"coordinates\" and closing }". Otherwise I think it's OK.

In the jBuilder I originally had json.type "LineString" in the json.geometry do loop and it's even worse adding: "geometry":{"type":"LineString","coordinates":"{\"type\":\"LineString\",\"coordinates\".

As Зелёный pointed out json.coordinates JSON.parse(street.extent_json) replacing similar line was needed. As he also pointed out I must have had some malformed json inputs which I did. Once that was cleaned up everything is working.

He also pointed out "in jbuilder template all things must be in plain Ruby, but you pass a json string(which comes from database) as result Rails tried to convert json string to json again."

But output still has an error, here's the first item:

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {
        "title": "Was 10th St.  before 1903 and now is part of E. 9th Place (21). 1908)"
      },
      "geometry": {
        "coordinates": {
          "type": "LineString",
          "coordinates": [
            [
              -118.24982816353442,
              34.035546195508864
            ],
            [
              -118.25104052200915,
              34.03663976724366
            ]
          ]
        }
      }
    },

An extra { "coordinates": after geometry.

Upvotes: 2

Views: 290

Answers (2)

Greg
Greg

Reputation: 2609

To restate the problem: take a series of GeoJSONs from a database and use jBuilder to compile all the items that meet a certain criteria into a GeoJSON (for use in a Mapbox/Leaflet web map). https://stackoverflow.com/users/2057388/Зелёный provided the answer offline, but I want to document it to make sure I understand it and help anyone else with a similar problem. It helps to consider the jsons as hashes and that jbuilder is making another hash.

The input has two keys: type and coordinates.

The output has keys of type, properties, and geometry. The properties value is a key title; the geometry values are two keys type and coordinates. So overview_data.json.builder becomes:

extent = JSON.parse(street.extent_json) # the GeoJSON 
json.type "Feature"

json.properties do
   json.title h("Was #{street.prevName} before #{street.dateEarliest} and now is #{street.currentName} #{street.dateLatest}.")
end

json.geometry do
   json.type "LineString"
   json.coordinates extent["coordinates"]
end

Looks straightforward once it's laid out. Except for other key points. One was parsing extent_json to convert the string to a hash object. Then coordinates are extracted from that hash to put into the output json.

Upvotes: 1

Roman Kiselenko
Roman Kiselenko

Reputation: 44360

The problem is in extent_json method, it returns an object as json string. To resolve your issue, avoid the double call to_json.

Upvotes: 2

Related Questions