{
"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.
Related
I'm just getting started with Dataweave and trying to figure out how to transform data from this particular JSON response. I'm stumped after fairly exhaustively reading documentation and searching for examples. Can't find anything quite like it. Below is the payload I'm working with:
[
{
"columnMetadata": [
{
"name": "shape",
"columnIndex": 0,
"dataType": "string",
"schemaType": "Static"
},
{
"name": "color",
"columnIndex": 1,
"dataType": "string",
"schemaType": "Static"
}
],
"rowData": [
[
"square",
"yellow"
],
[
"circle",
"green"
],
[
"star",
"blue"
]
]
}
]
The transformation I'm trying to achieve is as such:
[
{
"shape": "square",
"color": "yellow"
},
{
"shape": "circle",
"color": "green"
},
{
"shape": "star",
"color": "blue"
}
]
Any help much appreciated!
The way to resolve this problem is by using dynamic objects This feature allows to dynamically compose an object from other objects or array the objects in this case. It is similar to the spread operator in js.
%dw 2.0
output application/json
---
payload flatMap ((item, index) -> do {
var metadataNames = item.columnMetadata map ((metadata, index) -> metadata.name)
---
item.rowData map ((datas, index) ->
{
(
datas map ((data, index) ->
{
(metadataNames[index]):data
}
)
)
}
)
})
This transform should work to get your output
payload..rowData flatMap (v) -> (v map ({shape: $[0], color: $[1]}))
If my understanding is correct, you wanted to pick data from rowData following the information found in columnMetadata (specific information will be picked based on columnIndex and key will be based on name i.e. shape should come from rowData[0] as columnMetadata.columnIndex is 0 and columnMetada.name is shape). This will mean that whatever information in columnMetadata will impact how you read the rowData.
You can attain this using combination of map and reduce. Reduce to iterate values of your columnMetadata and accumulate the result, and map to perform reduce for each member of your rowData.
See below dataweave:
%dw 2.0
output application/json
---
using (columnMetadata = flatten(payload.columnMetadata))
flatten(payload.rowData) map (row) -> columnMetadata reduce ((item, acc={}) -> acc ++ {(item.name): row[item.columnIndex]})
This will result to:
[
{
"shape": "square",
"color": "yellow"
},
{
"shape": "circle",
"color": "green"
},
{
"shape": "star",
"color": "blue"
}
]
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'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.
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}`);
}
});
What I'm trying to do is to find places which are inside or with 10 meters distance of a street.
My streets table has a geometry column which coordinates are saved from.
A sample coordinate looks like
{ "type": "Feature", "properties": { "id": 4.000000, "osm_id": 69551269.000000, "type": "tertiary", "name": "Street name", "tunnel": 0, "bridge": 0, "oneway": 1, "ref": null, "z_order": 4.000000, "access": null, "service": null, "class": "highway" },
"geometry": { "type": "LineString",
"coordinates": [ [ 45.055701068545773, 37.537045660463036 ], [ 45.055566036085651, 37.536995369044007 ], [ 45.054243455583901, 37.536797891405229 ], [ 45.053941120336447, 37.536756233346466 ], [ 45.053692177812167, 37.536712228354787 ], [ 45.052483758831642, 37.536435290273943 ], [ 45.052157870436275, 37.536344765719662 ], [ 45.051875819394468, 37.536229430731993 ], [ 45.05173206975504, 37.536151395213466 ], [ 45.051607347035826, 37.536067827638817 ], [ 45.051492766419436, 37.535979063284202 ], [ 45.050636052096081, 37.535314881276747 ], [ 45.050383253896371, 37.535111536305749 ], [ 45.050164989137727, 37.534882458892014 ], [ 45.050017048546714, 37.534692692604175 ], [ 45.049976061040212, 37.534639970433204 ], [ 45.049796436855189, 37.534394380670221 ], [ 45.049439032503869, 37.533859196152598 ], [ 45.049149186292141, 37.533424929749174 ], [ 45.048739143588875, 37.532811039160741 ], [ 45.048373357334377, 37.532213577102539 ], [ 45.048231284075598, 37.531903279047071 ], [ 45.048143022635173, 37.531710579093094 ], [ 45.047949568309946, 37.531336494754463 ], [ 45.047873628267183, 37.531189895267971 ], [ 45.047984772303266, 37.53111303321586 ] ] } },
My question is that should the coordinates be saved as polygon or LineString.
GeoJson authoritive indicates that LineString has no inside or outside but the data which I've got from openstreet(above is a sample) has a type of LineString.
So Which one should I use?
Edit:
A sample LineString from openstreetmap looks like this:
I drew them by drawing a polygon with coordinates.
Either of the two of geometry types, linestrings and polygon would work for you in your case. But i think it is quite straightforward to convert the linestrings to polygon and just use ST_Buffer the polygon with 20m...
SET #line = ST_GeomFromText('LINESTRING(44.9894318 37.496227, 44.9901579 37.4964403)',4326); SET #pt = ST_GeomFromText('POINT(45.00 37.4964)',4326); SET #buffer=st_buffer(#line,0.0124274); SELECT ST_WITHIN(#pt,#buffer)
20 meters = 0.0124274 mile,
Difference between Geography coordinate system and geometry coordinate system: https://en.wikipedia.org/wiki/Geographic_coordinate_system