I'm a beginner in ReactJS, I use react-leaflet for map rendering,
On this map I put some marker with coordinates point.
Short story, I try to get some object from JSON files, containing values by area, and coordinates points for polygon render on the map, it looks like this:
{
"type": "FeatureCollection",
"crs": {
"type": "name",
"properties": {
"name": "urn:ogc:def:crs:OGC:1.3:CRS84"
}
},
"features": [
{
"type": "Feature",
"id": 656,
"properties": {
"DCOMIRIS": "940180101",
"DEPCOM": "94018",
"NOM_COM": "Charenton-le-Pont",
"IRIS": "0101",
"TYP_IRIS": "H",
"DEP": "94",
"aire": 0.2069,
"population": 3974
},
"geometry": {
"type": "MultiPolygon",
"coordinates": [
[
[
[2.4197, 48.8214],
[2.4196, 48.8205],
[2.4196, 48.8199],
[2.4196, 48.819],
[2.4196, 48.8181],
[2.4196, 48.8172],
[2.4196, 48.8169],
[2.4183, 48.8167],
[2.418, 48.8166],
[2.4166, 48.8164],
[2.4159, 48.8163],
[2.4159, 48.8163],
[2.4159, 48.8163],
[2.4155, 48.817],
[2.4152, 48.8175],
[2.4149, 48.8178],
[2.4148, 48.8181]
]
]
]
}
},
{
"type": "Feature",
"id": 657,
"properties": {
"DCOMIRIS": "940180109",
"DEPCOM": "94018",
"NOM_COM": "Charenton-le-Pont",
"IRIS": "0109",
"TYP_IRIS": "H",
"DEP": "94",
"aire": 0.4146,
"population": 3906
},
"geometry": {
"type": "MultiPolygon",
"coordinates": [
[
[
[2.4055, 48.8245],
[2.4053, 48.8244],
[2.4042, 48.8235],
[2.4032, 48.8226],
[2.4024, 48.8219],
[2.4014, 48.8211],
[2.4013, 48.821],
[2.4011, 48.8209],
[2.401, 48.8207],
[2.4009, 48.8207],
[2.4009, 48.8206],
[2.4007, 48.8207],
[2.3996, 48.8212]
]
]
]
}
}
With underscore I try to get some object with coordinates value, like this:
var find = _.findWhere(this.state.data, {coordinates: [2.4055, 48.8245]});
but I got nothing, I don't know how to search "deeper" in my json.
If I try:
var find = _.findWhere(this.state.data, {id: 656});
underscore get me the object...
Any advice?
The problem you are facing is that the find method is probably comparing each of the json coordinates object, like:
"coordinates": [
[
[
[2.4055, 48.8245],
[2.4053, 48.8244],
[2.4042, 48.8235],
[2.4032, 48.8226],
[2.4024, 48.8219],
[2.4014, 48.8211],
[2.4013, 48.821],
]
]
]
With the object you provide:
"coordinates":
[2.4055, 48.8245]
And this comparison returns false.
As far as I understood you're searching for a "feature" object inside a JSON that contains coordinates [2.4055, 48.8245].
You need to do several steps to search for an element:
Loop through the features property.
Find your coordinate inside geometry.coordinates array.
The problem here could be that the coordinates array could be nested because it is a MultiPolygon object. It may be a one level deep:
[ [ 1.1, 2.2 ], [ 3.3, 4.4 ] ]
... or two and more levels deep like in your example:
[ [ [ 5.1, 6.2 ], [ 7.3, 8.4 ] ] ]
In this case you need to do a search using recursion.
Here is how this could be done with lodash or underscore (I tested with lodash).
// Recursive search function.
function find(coords, items) {
var i = 0, found;
for (; i < items.length; i++) {
if (_.isArray(items[i])) {
if (items[i].length === 2 && _.isNumber(items[i][0]) && _.isNumber(items[i][1]) && _.isEqual(items[i], coords)) {
return items[i];
} else {
found = find(coords, items[i]);
if (found) {
return found;
}
}
}
}
}
// Coordinates you're looking for
var coords = [2.4055, 48.8245];
// Loop through the features and find coordinates.
var result = _.find(_.get(data, 'features'), function (feature) {
return find(coords, _.get(feature, 'geometry.coordinates'));
});
The result is a "feature" object that contains coordinate that you're looking for.
Related
I am looking to try make it easier to use the Google Analytics data in Google sheets.
The outputs that I receive from the api look like :
[
{
"dimensionValues": [
{
"value": "id2"
},
{
"value": "(not set)"
},
{
"value": "Android"
}
]
},
{
"dimensionValues": [
{
"value": "id1"
},
{
"value": "stream name"
},
{
"value": "iOS"
}
]
}
]
Whats the most efficient method to remove the field names to make a "flatter set of arrays" similar to:
[["id2","(not set)","Android"], ["id1","stream name","iOS"]]
It feels like there should be a quick way to do this!
You can use a double map for this one. Map the value to its dimensionValues and then map those to the array elements to get the designated output.
let array = [{"dimensionValues": [{"value": "id2"},{"value": "(not set)"},{"value": "Android"}]},{"dimensionValues": [{"value": "id1"},{"value": "stream name"},{"value": "iOS"}]}]
console.log(array.map(x => x.dimensionValues.map(y => y.value)))
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
126.9823439963945,
37.56461982743129
]
}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[
126.9823439963945,
37.56461982743129
],
[
126.98230789017299,
37.564453179812105
],
[
126.98210513804034,
37.563703265276516
],
[
126.98207180945346,
37.56352550784786
],
[
126.9817857308457,
37.56284502921221
],
[
126.98166907678578,
37.562633941789535
],
[
126.98157186492477,
37.56247284870586
],
[
126.98128300624569,
37.56205345097403
],
[
126.98124689891416,
37.56200067907546
]
],
"traffic": [0, 8, 4, 12]
}}
This is what I got.
And I don't have any idea to parse key "coordinates".
This type depends on type of geometry.
If type is "Point", type became [String].
If type is "LineString", type became [[String]].
How can I solve it?
You can use this cocoa pod: CodableGeoJSON.
It has the Codable structs written up for you. You seem to have a feature with an unknown geometry here, so you can do something like this:
let geoJSON = try JSONDecoder().decode(GeoJSON.self, from: geoJSONData)
guard case .feature(let feature) = geoJSON else {
// the GeoJSON does not contain a feature!
}
// handle each kind of geometry...
switch feature.geometry {
case .point(let coordinates): // coordinates is a GeoJSONPosition
// ...
case .multiPoint(let coordinates): // coordinates is a [GeoJSONPosition]
// ...
case .lineString(let coordinates): // coordinates is a [GeoJSONPosition]
// ...
case .multiLineString(let coordinates): // coordinates is a [[GeoJSONPosition]]
// ...
case .polygon(let coordinates): // coordinates is a [[GeoJSONPosition]]
// ...
case .multiPolygon(let coordinates): // coordinates is a [[[GeoJSONPosition]]]
// ...
case .geometryCollection(let geometries):
// ...
}
If you don't like using a library just for this, have a look at their source code and try to learn from it, specifically, GeoJSON.swift.
I want to print out JSON images as a variable.
This is my local JSON file (JsonData.json):
{
"appetizer": [
{
"num": "appetizer1",
"name": "salad",
"condition": [ "1", "2" ],
"image": "./appetizer/salad.png"
},
{
"num": "appetizer2",
"name": "soup",
"condition": [ "2", "3" ],
"image": "./appetizer/soup.png"
},
…
],
"main": [
{
"num": "main1",
"name": "beef",
"condition": [ "1" ],
"image": "./main/beef.png"
},
{
"num": "main2",
"name": "fish",
"condition": [ "2", "3" ],
"image": "./main/fish.png"
},
…
]
}
I filtered the name when condition="2". (salad,soup,fish)
This is the code for filtering name:
const newArray1 = [...JsonData["apptizer"], ...JsonData["main"]];
const JsonResult = newArray1.filter(item => {
if(item.condition.indexOf("2") !== -1) return item.name;
});
AND I want to get the image when condition="2".
How can I get them? And How can I print out them?
Do I have to use base64? If so, Can you tell me how to use it?
I saw the explanation, but I can't understand it.
And I imported JSON file this way (I've been correctly using it):
var JsonData = require('./JsonData.json');
You can use below code:
let mainObject = JSON.parse(JSON.stringify(data))
let allKeys = Object.keys(mainObject)
let finalObject = []
allKeys.map((value, index) => {
let array = mainObject[value]
array.map((aryObject, aryIndex) => {
let condition = aryObject['condition']
if (condition.includes('2')) {
finalObject.push(aryObject)
}
})
})
alert(JSON.stringify(finalObject))
You can import data in top of screen:
import { data } from './data';
You can add below text in data.js:
export const data = {
"appetizer": [
{
"num": "appetizer1",
"name": "salad",
"condition": ["1"],
"image": "./appetizer/salad.png"
},
{
"num": "appetizer2222",
"name": "soup",
"condition": ["2", "3"],
"image": "./appetizer/soup.png"
},
],
"main": [
{
"num": "main1",
"name": "beef",
"condition": ["1"],
"image": "./main/beef.png"
},
{
"num": "main2",
"name": "fish",
"condition": ["21", "3"],
"image": "./main/fish.png"
},
]
}
You can use Object#values to get the arrays corresponding to appetizer and main and then Array#flat to extract the nested objects into a transformed array. Then use the Array#filter (which you are already using) to filter out only the required objects based on your condition and then Array#map to get the name and image values out of every filtered object into an array of objects.
Please consider following snippts
const jsonData = {"appetizer":[{"num":"appetizer1","name":"salad","condition":["1","2"],"image":"./appetizer/salad.png"},{"num":"appetizer2","name":"soup","condition":["2","3"],"image":"./appetizer/soup.png"}],"main":[{"num":"main1","name":"beef","condition":["1"],"image":"./main/beef.png"},{"num":"main2","name":"fish","condition":["2","3"],"image":"./main/fish.png"}]};
const filteredValues = Object.values(jsonData)
.flat()
.filter(o => o.condition.includes('2'))
.map(({name, image}) => ({ name, image }));
console.log(filteredValues);
The output of the above code will be an array of objects having the following structure
[{
"name": SOME_NAME,
"image": SOME_PATH
},
{
"name": SOME_NAME,
"image": SOME_PATH
},
...
]
You can use the above array to retrieve your image path and display it accordingly.
I think you shouldn't be worried about base64 as images are stored locally and path will be sufficient to display the image.
Hope this will help!!!
Side Note: You can avoid the Array#flat part as you are already doing it manually [...JsonData["apptizer"], ...JsonData["main"]] but flat will be handy in case there are more keys in jsonData that need to be considered.
First of all, I'm very new to JSON concept so sorry if my question is silly or very simple to answer.
I want to use Oxford Dictionary API for simple app which I'm writing in Kotlin, here is the response from API as JSON:
{
"metadata": {
"provider": "Oxford University Press"
},
"results": [
{
"id": "hello",
"language": "en",
"lexicalEntries": [
{
"entries": [
{
"etymologies": [
"early 19th century: variant of earlier hollo; related to holla"
],
"homographNumber": "000",
"senses": [
{
"definitions": [
"used as a greeting or to begin a telephone conversation"
],
"examples": [
{
"text": "hello there, Katie!"
}
],
"id": "m_en_gbus0460730.012",
"short_definitions": [
"used as greeting"
],
"subsenses": [
{
"definitions": [
"used to express surprise"
],
"examples": [
{
"text": "hello, what's all this then?"
}
],
"id": "m_en_gbus0460730.017",
"regions": [
"British"
],
"short_definitions": [
"used to express surprise"
]
},
{
"definitions": [
"used as a cry to attract someone's attention"
],
"examples": [
{
"text": "‘Hello below!’ he cried"
}
],
"id": "m_en_gbus0460730.018",
"short_definitions": [
"used attract attention"
]
},
{
"definitions": [
"used informally to express sarcasm or anger"
],
"examples": [
{
"text": "Hello! Did you even get what the play was about?"
}
],
"id": "m_en_gbus0460730.019",
"short_definitions": [
"used informally to express sarcasm or anger"
]
}
]
And now, I would like to extract only "definitions" from this JSON object but as you can see it is nested within other JSON arrays, my code so far looks like this:
var resultJSON = JSONObject(result)
var JSON_results = resultJSON.getJSONArray("results")
var JSON_lexical = JSON_results.getJSONObject(0).getJSONArray("lexicalEntries")
var JSON_entries = JSON_lexical.getJSONObject(0).getJSONArray("entries")
var JSON_senses = JSON_entries.getJSONObject(0).getJSONArray("senses")
var JSON_definitions = JSON_senses.getJSONObject(0).getJSONArray("definitions")
Log.i("JSON", JSON_definitions.getString(0))
I know that there needs to be a better way of doing this but I can't find how.
Kotlin actually makes it easier to map such responses with something called "data classes". So you can simply paste the JSON response in an online JSON to Kotlin Data Class Generator e.g. https://json2kotlin.com
It churns out .kt files like this:
data class Json4Kotlin_Base (
val metadata : Metadata,
val results : List<Results>
)
and thn you can simply pass on the response JSON to the Data class mapping like this:
val json = getJson() // your json value here
val topic = Gson().fromJson(json, Json4Kotlin_Base::class.java)
In case you're looking for GSON annotations in the generated models, chose the option when you generate those.
Here's a video tutorial for step by step process about it.
https://www.youtube.com/watch?v=n46WbgNoEnE
Try as follow
val justDefinitions = mutableListOf<String>()
JSON_senses.forEach {
val definitions = it.getJSONArray("definitions")
for (i in 0 until definitions.length()) { {
justDefinitions.add(it.getString(i))
}
}
I have my custom 'latitude' and 'longitude' variable.
var custom_loc = [50.34434, 63.23442]
And also I have JSON data with points in GeoJSON format.
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [50.34434, 63.23442]
},
"properties": {
"id" : "1",
"name": "Good place"
}
}
How I can find JSON marker by "custom_loc" and get JSON property (for e.x. "ID")?
I use leaflet.js in my project.
You can use a markers getLatLng() method to access its latlng and then match it with your custom location. To bind the id to the layer your best bet is to add the geoJSON feature to a L.GeoJSON layer and access the id via layer.feature.properties.id or bind the id to the layer via onEachFeature method passed into L.GeoJSON options.
Then whenever you want to find the layer with the matching latlng just loop through your geojson layer using the eachlayer method e.g.:
var custom_loc = [50.34434, 63.23442];
var geoJSON = L.geoJson(
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [50.34434, 63.23442]
},
"properties": {
"id" : "1",
"name": "Good place"
}
}
]
},
{
onEachFeature: function(feature, layer) {
layer.options.id = feature.properties.id;
}
}
);
map.addLayer(geoJSON);
geoJSON.eachLayer(l => {
var coords = l.feature.geometry.coordinates;
var latlng = l.getLatLng();
if (latlng.lat === custom_loc[1] && latlng.lng === custom_loc[0]) {
console.log(`Latlng match: ${l.options.id}`)
}
if (coords[0] === custom_loc[0] && coords[1] === custom_loc[1]) {
console.log(`Latlng match: ${l.options.id}`);
}
});