Ben Ben - 1 month ago 10
Ajax Question

Double parse JSON data (or use another method to split)

Wondering what the best way is to break a large data object coming from AJAX apart. If I send just one portion (says paths) I use

JSON.parse(data)
What I'd really like to do is split the object apart first into it's individual blocks, then be able to do something like
JSON.parse(data['paths'])
.

Here's a clipped sample of the JSON data

{
"paths": {
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"geometry": {
"type": "MultiLineString",
"coordinates": [
[
[-122.32074805731085, 47.634990818586026],
[-122.32074412999432, 47.63497931696752],
[-122.32107629703529, 47.63465666282262]
]
]
},
"properties": {
"path_name": "Woodland path"
},
"id": 2
}]
},
"beds": {
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"geometry": {
"type": "MultiPolygon",
"coordinates": [
[
[
[-122.32073753862116, 47.6347629704532],
[-122.32071585642394, 47.63470617810399],
[-122.32073753862116, 47.6347629704532]
]
]
]
},
"properties": {
"bed_name": "Azalea Triangle"
},
"id": 1
}]
}
}


Here's what I have in javascript

$.ajax
dataType: 'text'
url: 'map.json'
success: (data) ->


Here's the Rails code that generates the call

data = { buildings: @geopaths, lawns: @geobeds }

respond_to do |format|
format.json { render json: data }
format.html
end


UPDATE:
I had sort of avoided explaining what I was wanting to do because I thought it would confuse the issue. In a nut shell - I am collecting data from a database, and sending it to Javascript to be displayed as layers on a map. Each layer has a name (paths, beds, etc), and gets encoded as GeoJSON in Rails before being sent to Javascript with an AJAX command. If I only send one layer I have no trouble parsing the data and getting it onto the map. A typical line of code would look like
pathMarkers = L.geoJSON(JSON.parse(data))
.

I now need to pass multiple layers to the map. My understanding is AJAX can only handle one object so I combine both paths and beds into one object. When I get to the Javascript side I don't know what to do. In other words I need to get only that portion of the object that has path data for the pathMarkers, and only that portion of the object that has bed data for the bedMarkers.

Graphically this is what I'm trying to do:

paths = a bunch of GeoJSON data
beds = a bunch of GeoJSON data
Use AJAX to send paths and beds to javascript
build pathMarkers with JSON.parse for the paths data
build bedsMarkers with JSON.parse for the beds data


I could build a sample and post it to bitbucket if it would help.

Answer

Assuming that I understood correctly and your concern is bringing in distinct data layers into a geo library like Leaflet.js, a single AJAX request is fine unless the JSON payload is so large that it crashes the browser.

As you don't provide much of your code, the following is a general example of how you would do it.

First you create the map object. Obviously :)

const map = L.map(id).setView([1.2345, -1.2345], 10);

Start the AJAX request to fetch the geoJSON file.

$.ajax({
  dataType: "json",
  url: '/json/lives/here.json',
  data: {} /* any props you'd like to pass as query string to your server */,
  success: success
});

And the crux of the issue: "How do I access each feature collection?"
The sucess or done callback is where you can be sure you received the data, and can add it to the map.

jQuery's AJAX method, when called with dataType: 'json', automatically runs JSON.parse() for you (and a couple of other things). Once the JSON is parsed, it can be accessed as any other object in JS. At this point the success callback receives the JSON-turned-into-object, which you can access with traditional JS methods. Like so:

function success (data) {
    // data is the parsed JSON. It is now just a JS object.
    // Below: for every "key" in the data object, pass its data to L.geoJSON() and add it to the map.
    for (var geojsonFeatureCollection in data) {
        if (data.hasOwnProperty(geojsonFeatureCollection)) {
            L.geoJSON(geojsonFeatureCollection, {/* options */}).addTo(map);
        }
    }
}

To answer your point about AJAX and a single object: AJAX is a just like any other browser request.
Yes you do send one request at a time. And likewise you receive one response from the server. But what is contained in the response can be absolutely any data. So what you are doing server side is totally OK!

In your case the data consists of a JSON text file, which is later parsed and turned into a JS object for you to actually do something with. The object contains a bunch of "keys" (beds, paths) and all you need to do is iterate over each of those keys and pass each one to Leaflet's geoJSON method for rendering.