Split JSON File Objects Into Multiple Files - javascript

I have a file with too many data objects in JSON of the following form:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-37.880859375,
78.81903553711727
],
[
-42.01171875,
78.31385955743478
],
[
-37.6171875,
78.06198918665974
],
[
-37.880859375,
78.81903553711727
]
]
]
}
},
{
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-37.6171875,
78.07107600956168
],
[
-35.48583984375,
78.42019327591201
],
[
-37.880859375,
78.81903553711727
],
[
-37.6171875,
78.07107600956168
]
]
]
}
}
]
}
I would like to split the large file such that each features object would have its own file containing a its type object and features(coordinates) object. So essentially, I am trying to get many of these:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-37.6171875,
78.07107600956168
],
[
-35.48583984375,
78.42019327591201
],
[
-37.880859375,
78.81903553711727
],
[
-37.6171875,
78.07107600956168
]
]
]
}
}
]
}

Here's a solution requiring just one invocation of jq and one of awk, assuming the input is in a file (input.json) and that the N-th component should be written to a file /tmp/file$N.json beginning with N=1:
jq -c '.features = (.features[] | [.]) ' input.json |
awk '{ print > "/tmp/file" NR ".json"}'
An alternative to awk here would be split -l 1.
If you want each of the output files to be "pretty-printed", then using a shell such as bash, you could (at the cost of n additional calls to jq) write:
N=0
jq -c '.features = (.features[] | [.])' input.json |
while read -r json ; do
N=$((N+1))
jq . <<< "$json" > "/tmp/file${N}.json"
done
Each of the additional calls to jq will be fast, so this may be acceptable.

PowerShell solution (requires PowerShell v3 or newer):
$i = 0
Get-Content 'C:\path\to\input.json' -Raw |
ConvertFrom-Json |
Select-Object -Expand features |
ForEach-Object {
$filename = 'C:\path\to\feature{0:d5}.json' -f ($i++)
$properties = [ordered]#{
type = 'FeatureCollection'
features = $_
}
New-Object -Type PSObject -Property $properties |
ConvertTo-Json -Depth 10 |
Set-Content $filename
}

I haven't tested this code properly. But should provide you some idea on how you can solve the problem mentioned above
var json = {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-37.880859375,
78.81903553711727
],
[
-42.01171875,
78.31385955743478
],
[
-37.6171875,
78.06198918665974
],
[
-37.880859375,
78.81903553711727
]
]
]
}
},
{
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-37.6171875,
78.07107600956168
],
[
-35.48583984375,
78.42019327591201
],
[
-37.880859375,
78.81903553711727
],
[
-37.6171875,
78.07107600956168
]
]
]
}
}
]
}
$(document).ready(function(){
var counter = 1;
json.features.forEach(function(feature){
var data = {type: json.type, features: [feature]}
var newJson = JSON.stringify(data);
var blob = new Blob([newJson], {type: "application/json"});
var url = URL.createObjectURL(blob);
var a = document.createElement('a');
a.download = "feature_" + counter + ".json";
a.href = url;
a.textContent = "Download feature_" + counter + ".json";
counter++;
document.getElementById('feature').appendChild(a);
document.getElementById('feature').appendChild(document.createElement('br'));
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="feature"></div>

Related

get bounds of featureCollection in d3

From this gist https://gist.github.com/mbertrand/5218300 I got some sample-code for drawing some features, which I adopted to use my GeoJSON
var features = [
{ "type": "Feature", "properties": { }, "geometry": { "type": "MultiLineString", "coordinates": [ [ [ 13.3921498, 52.476596, 31.64 ], [ 13.393036, 52.4765996, 31.6 ], [ 13.3934, 52.4765511, 31.87 ], [ 13.3935847, 52.4765058, 32.37 ], [ 13.3936657, 52.4764735, 32.16 ], [ 13.3936851, 52.4764164, 32.04 ], [ 13.3936229, 52.4761477, 32.05 ], [ 13.3934819, 52.4758929, 32.77 ], [ 13.3932546, 52.4756262, 32.56 ], [ 13.3930283, 52.4754013, 32.51 ], [ 13.3927091, 52.4751468, 32.64 ], [ 13.3923208, 52.4749337, 32.63 ], [ 13.3919094, 52.4747933, 33.13 ], [ 13.3917874, 52.4747948, 32.61 ], [ 13.391795, 52.4747857, 32.75 ], [ 13.3918985, 52.4747159, 33.03 ], [ 13.3921305, 52.4748218, 32.9 ], [ 13.3924295, 52.4749522, 32.21 ], [ 13.392583, 52.475059, 32.49 ], [ 13.3931511, 52.4753106, 32.74 ] ] ] } },
{ "type": "Feature", "properties": { }, "geometry": { "type": "MultiLineString", "coordinates": [ [ [ 13.3931511, 52.4753106, 32.74 ], [ 13.3934351, 52.475342, 32.43 ] ] ] } }
];
var bounds = d3.geo.bounds(features),
topLeft = bounds[0],
bottomRight = bounds[1];
However when debugging the script, topLeft and bottomRight are NaN.
I suppose this is because of the more complex geometry-structure of my JSON, which consists of MultiLineString-geometries, nit just simple Point-features. Any idea how to get the bounds here?
Generally speaking, D3 geo functions that accept geojson only accept geojson objects, not arrays. If you nest your features in a FeatureCollection, you should see a result:
var collection = { type: "FeatureCollection", features: features }
var features = [
{ "type": "Feature", "properties": { }, "geometry": { "type": "MultiLineString", "coordinates": [ [ [ 13.3921498, 52.476596, 31.64 ], [ 13.393036, 52.4765996, 31.6 ], [ 13.3934, 52.4765511, 31.87 ], [ 13.3935847, 52.4765058, 32.37 ], [ 13.3936657, 52.4764735, 32.16 ], [ 13.3936851, 52.4764164, 32.04 ], [ 13.3936229, 52.4761477, 32.05 ], [ 13.3934819, 52.4758929, 32.77 ], [ 13.3932546, 52.4756262, 32.56 ], [ 13.3930283, 52.4754013, 32.51 ], [ 13.3927091, 52.4751468, 32.64 ], [ 13.3923208, 52.4749337, 32.63 ], [ 13.3919094, 52.4747933, 33.13 ], [ 13.3917874, 52.4747948, 32.61 ], [ 13.391795, 52.4747857, 32.75 ], [ 13.3918985, 52.4747159, 33.03 ], [ 13.3921305, 52.4748218, 32.9 ], [ 13.3924295, 52.4749522, 32.21 ], [ 13.392583, 52.475059, 32.49 ], [ 13.3931511, 52.4753106, 32.74 ] ] ] } },
{ "type": "Feature", "properties": { }, "geometry": { "type": "MultiLineString", "coordinates": [ [ [ 13.3931511, 52.4753106, 32.74 ], [ 13.3934351, 52.475342, 32.43 ] ] ] } }
];
var collection = { type: "FeatureCollection", features: features }
var bounds = d3.geo.bounds(collection),
topLeft = bounds[0],
bottomRight = bounds[1];
console.log(bounds);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>

GeoJSON file making leaflet API slow site down

I'm trying to use the leaflet API to display data about Coral Reef locations across the world. I originally downloaded a shapefile (.shp), and converted it to GeoJSON using QGIS. I put the data in my project folder, but when I attempted to display this data on leaflet through an Ajax request, the browser took a very long time to load and eventually return a not responding message. However, I could see that the markers would appearing on the map, albeit it very slowly. Is there any way to create a smaller file, or load the data more efficiently so it doesn't make the entire site unusable?
My Ajax request looked like this:
$.ajax({
type: 'GET',
url: './coldwater.geojson',
dataType: 'json',
data: data,
success: function (data) {
L.geoJSON(data).addTo(mymap);
}, error: function(){
console.log('Couldn\'t load data');
}
});
Here's a snippet of the geoJSON
{
"type": "FeatureCollection",
"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } },
"features": [
{ "type": "Feature", "properties": { }, "geometry": { "type": "MultiPoint", "coordinates": [ [ -75.116700000304718, 18.283300000094982 ], [ -75.116699858211859, 18.283301156623111 ] ] } },
{ "type": "Feature", "properties": { }, "geometry": { "type": "MultiPoint", "coordinates": [ [ -34.850000000399632, 9.01670000040474 ], [ -34.849996660317572, 9.016695959750791 ] ] } },
{ "type": "Feature", "properties": { }, "geometry": { "type": "MultiPoint", "coordinates": [ [ -34.850000000399632, 9.01670000040474 ], [ -34.849996660317572, 9.016695959750791 ] ] } },
{ "type": "Feature", "properties": { }, "geometry": { "type": "MultiPoint", "coordinates": [ [ -81.166699999905006, 23.983300000394763 ], [ -81.166699953140267, 23.983303104854429 ] ] } },
{ "type": "Feature", "properties": { }, "geometry": { "type": "MultiPoint", "coordinates": [ [ -79.549997733808311, 26.649999766076405 ], [ -79.416700222836994, 27.166696245435446 ], [ -79.416700222836994, 27.283302340130945 ], [ -79.416699999805132, 27.283300000094982 ] ] } },
{ "type": "Feature", "properties": { }, "geometry": { "type": "MultiPoint", "coordinates": [ [ -78.683303107752181, 27.416698775628049 ] ] } },
{ "type": "Feature", "properties": { }, "geometry": { "type": "MultiPoint", "coordinates": [ [ -79.216699996607531, 24.099999131754601 ], [ -78.850001440414133, 26.516702255105031 ], [ -78.39999868309269, 26.583297050818317 ] ] } },
{ "type": "Feature", "properties": { }, "geometry": { "type": "MultiPoint", "coordinates": [ [ -77.083301298815854, 25.166702977260627 ] ] } },
{ "type": "Feature", "properties": { }, "geometry": { "type": "MultiPoint", "coordinates": [ [ -79.233301481578053, 27.216698550297906 ], [ -79.216699996607531, 27.300002749627254 ] ] } },
{ "type": "Feature", "properties": { }, "geometry": { "type": "MultiPoint", "coordinates": [ [ -79.549997733808311, 26.649999766076405 ], [ -79.416700222836994, 27.166696245435446 ], [ -79.416699999805132, 27.166700000104981 ], [ -79.366697917974477, 27.533295877103114 ] ] } },
Would it be better to use the google maps API?
Or is there a better way to insert a shapefile into a leaflet map?
ps: if this isn't appropriate or is off topic let me know. I'm new to posting on stackoverflow

*pointsWithinPolygon* on Trufjs

I'm trying to get some point inside multiple polygon using pointsWithinPolygon in turfjs, but the result is unexpected.
Is there any chance that pointsWithinPolygon isn't compatible with FeatureCollection?
Here is the example of my usage.
let points = {
"type": "Point",
"coordinates": [
106.866995, -6.261513
]
}
let filter = {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"IdArea": 4
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
106.314674,
-6.6348689124
],
[
107.5781628906,
-6.6348689124
],
[
107.5781628906,
-5.9742195859
],
[
106.314674,
-5.9742195859
],
[
106.314674,
-6.6348689124
]
]
]
}
}
]
}
let result = turf.pointsWithinPolygon(points, filter);
console.log(result);
You are trying to use geoJsons as inputs to turf's pointsWithinPolygons function.
The function takes a turf.points array of points, and a turf.polygon array of polygon vertices.
Based on the variables you established, you would need to call:
let result = turf.pointsWithinPolygon(turf.points([points.coordinates]), turf.polygon(filter.features.geometry.coordinates));

Create FeatureCollection from multiple GeoJSON strings

I have a list of features and I want to create a FeatureCollection to group them in one string, the features are from different types (polygons, lines and points).
Here is how they are written :
{
"type": "Feature",
"properties": {},
"geometry": {
"type": "LineString",
"coordinates": [
[
-31.640625,
15.623036831528264
],
[
-2.8125,
-14.264383087562637
],
[
-22.5,
-30.751277776257812
],
[
-30.937499999999996,
-38.54816542304657
]
]
}
}
{
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-24.960937499999996,
29.84064389983441
],
[
-2.109375,
21.616579336740603
],
[
2.4609375,
43.068887774169625
],
[
-31.289062500000004,
49.38237278700955
],
[
-24.960937499999996,
29.84064389983441
]
]
]
}
}
Is there a javascript function that deals with this, i'm stuck on it.
If you have an array of GeoJSON feature strings, you can create a GeoJSON feature collection string like this:
var features = [
'{ "type": "Feature", "properties": {}, ... }',
'{ "type": "Feature", "properties": {}, ... }'
];
var collection = JSON.stringify({
features: features.map(JSON.parse),
type: 'FeatureCollection'
});

Not able to Parse a Json File

I want to load a GeoJson File that is uploaded on server
var promise = ('https://api.myjson.com/bins/31e3j');
that.map.data.loadGeoJson(promise);
This condition works fine
But I want to Load this GeoJson File locally
so I have assigned the Json Code instead a the Server Link to a Variable on which I am neither getting any error but unable to get the O/P as well
var promise = jQuery.parseJSON ('{ "type": "FeatureCollection","crs":{"type": "name","properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84"}},"features": [{"type": "Feature", "properties": {"id": 1},"geometry": {"type": "Polygon", "coordinates": [ [ [ -83.52936044652942, 40.30230752849768], [ -83.52924865349425, 40.30230753872012], [ -83.52924666169983, 40.3021800251207 ], [ -83.52935848418728, 40.302181900418084 ], [ -83.52936044652942, 40.30230752849768]]]}}, ]}');
that.map.data.loadGeoJson(promise);
When in doubt, run it through a linter/formatter:
http://jsonlint.com/
You have an error in the JSON, a comma a few characters from the end:
]]]}}, ]}');
^-------TROUBLE MAKER!
Or this one is cool!
http://pro.jsonlint.com/
I am neither getting any error
Maybe the surrounding code is swallowing the error. If you take your var promise = jQuery.parseJSON('DODGY_JSON_HERE') code and run it in the console, you'll see the error:
Uncaught SyntaxError: Unexpected token ](…)
e.extend.parseJSON #jquery.min.js:2
(anonymous function) #VM270:2
InjectedScript._evaluateOn #VM268:875
InjectedScript._evaluateAndWrap #VM268:808
InjectedScript.evaluate #VM268:664
Not as handy as the linter, but at least you see an error.
Invalid JSON is not parseable, obviously:
...snip...[ -83.52936044652942, 40.30230752849768]]]}}, ]}');
^----
Because that isn't correct JSON. You have additional comma at the end.
{ "type": "FeatureCollection","crs":{"type": "name","properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84"}},"features": [{"type": "Feature", "properties": {"id": 1},"geometry": {"type": "Polygon", "coordinates": [ [ [ -83.52936044652942, 40.30230752849768], [ -83.52924865349425, 40.30230753872012], [ -83.52924666169983, 40.3021800251207 ], [ -83.52935848418728, 40.302181900418084 ], [ -83.52936044652942, 40.30230752849768]]]}} ]}
This is correct JSON:
{
"type": "FeatureCollection",
"crs": {
"type": "name",
"properties": {
"name": "urn:ogc:def:crs:OGC:1.3:CRS84"
}
},
"features": [
{
"type": "Feature",
"properties": {
"id": 1
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-83.52936044652942,
40.30230752849768
],
[
-83.52924865349425,
40.30230753872012
],
[
-83.52924666169983,
40.3021800251207
],
[
-83.52935848418728,
40.302181900418084
],
[
-83.52936044652942,
40.30230752849768
]
]
]
}
}
]
}

Categories

Resources