I have json from an open data API that I need to convert into geojson so that it can be displayed as layer on my Mapbox map. I am using Mapbox GL JS library: https://docs.mapbox.com/mapbox-gl-js/api/. Here's the link to the open data json api: https://data.cityofnewyork.us/resource/64uk-42ks.json.
I can successfully fetch the json api and print it to console, but now I need to convert it to a geojson. I know that I can do this entirely frontend because it is open data.
Here's my code:
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/niki12step/ck8q9fgpx00d91ipipual7mrl', // replace this with your style URL
center: [-73.961581,40.683868],
zoom: 9.5
})
var pluto_url = 'https://data.cityofnewyork.us/resource/64uk-42ks.json'
getData();
async function getData () {
await fetch(pluto_url)
.then(response => response.json())
.then(data => console.log(data))
}
A GeoJSON file typically looks like this:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [75, 25]
},
"properties": {
"name": "earth"
}
}
]
}
"features" is the list of all your features. Each feature is a object with the keys "type", "geometry" and "properties" and eventually "id".
That means you have to loop through all data points in your JSON file and convert it to this format. This could look like this:
const pluto_url = 'https://data.cityofnewyork.us/resource/64uk-42ks.json';
getData();
async function getData () {
let mygeojson = {"type": "FeatureCollection", "features": []}
await fetch(pluto_url)
.then(response => response.json())
.then(data => {
for(let point of data){
let coordinate = [parseFloat(point.longitude), parseFloat(point.latitude)];
let properties = point;
delete properties.longitude;
delete properties.latitude;
let feature = {"type": "Feature", "geometry": {"type": "Point", "coordinates": coordinate}, "properties": properties}
mygeojson.features.push(feature);
}
});
console.log(mygeojson);
}
I assumed that you only have Point geometries. I used parsedFloat() because coordinates are stored as String in your file but the GeoJSON format required float values. With delete properties.longitude and delete properties.latitude I achieve that the coordinates are not needlessly part of the properties field.
Related
i want to retrieve some array inside an array but i dont know how, please read my explanation first
here is my json response
{
"Value": [
{
"id": "5ff97d740e788778dd66ee25",
"id_order": "ORD-434183",
"nama_pelanggan": "Herman",
"total": 80000.0,
"jumlah_item": 4.0,
"cart": [
{
"id_cart": "CART-112010",
"nama_produk": "Ayam Bakar",
"jumlah": 4.0,
"harga": 20000.0,
"subtotal": 80000.0,
"notes": "ga ada"
}
],
"admin_no": "ADM-431525",
"admin_name": "Admin",
"created_at": "2021-01-09 16:55:00",
"updated_at": "2021-01-09 16:55:00"
}
],
"Status": true,
"Messages": [
{
"Type": 200,
"Title": "TotalRows",
"Message": "1"
}
]}
as you can see the value of "value" is an array and in that array also have an array "cart"
i want to retrieve this array "cart" and put it in a table
here is how i retrieve the response using vue js Mapping an Array to Elements with v-for
var vm = new Vue({
el: '#app',
data: {
list: {
items: [],
},
}
var formData = new FormData();
formData.append('filterparams', JSON.stringify(filters));
formData.append('display', JSON.stringify(_self.list.config.display));
formData.append('auth', sessionStorage.getItem("token"));
_self.$http.post(hostapi + 'order/GetByParamsHistory', formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
});
var obj = response.data;
_self.list.items = obj.Value; // the value from array "Value"
here is the table html code
and now I don't know how to insert an existing array in the array into the html table
You can access the array on the basis of the array index.
Suppose, if list contains the json response's value field then you can access it like.
list['0'].cart.
Im building a React app and I have a quite complex JSON file where I need to find and output certain values of an object in an array.
Im trying to output all my people from my JSON, they look something like this:
people: [
{
"id": 1,
"email": "Sincere#april.biz",
"address": [
{
"street": "Kulas Light",
"type": "house",
"attribute": {
"sketch": "sketch.jpg",
"photo": "photo.jpg"
}
},
{
"street": "Lorem Ipsum",
"type": "apartment",
"attribute": {
"sketch": "sketch.jpg",
"photo": "photo.jpg"
}
}
]
}
]
I have no problem to output the email, doing it like so:
var App = React.createClass({
getInitialState: function () {
return {
results: {}
}
},
componentDidMount() {
fetch(REQUEST_URL) // fetch from API, returns JSON
.then(res => res.json())
.then(data => {this.setState(
{ results: data.people}
);
})
},
renderResult : function(key){
return <Result key={key} index={key} details={this.state.results[key]}/>
},
render : function() {
return (
<ul>
{Object.keys(this.state.results).map(this.renderResult)}
</ul>
)
}
});
var Result = React.createClass({
render : function() {
return (
<li>
{this.props.details.email}
<img src="{this.props.details.address.type=house.attribute.photo}"/>
</li>
)
}
});
ReactDOM.render(App, document.querySelector('#app'));
However, now I need to output "photo" but only for "type": "house". I tried this but no luck, well aware that this is way off. Im quite new to handling JSON data and React and Google hasn't helped me even after a few hours of trying to solve this.
The .address property isn't an object but an array of objects so
.type is not available directly on .address:
this.state.results.people.address.type
// .type property doesn't exist on array
Solution:
You can use Array.prototype.filter on .address to obtain an array of objects that have a property type whose value is "house":
var houseAddresses = this.state.results.people.address.filter(function(value){
return value.type === "house";
});
Here, houseAddress will be an array of objects whose type value is 'house".
You can then loop through the array to create the relevant JSX using for, Array#forEach or Array#map. The following example uses Array#map:
const houseImgTags = houseAddresses.map(function(house, index){
return (
<img
src={house.attribute.photo}
key={'house'+index}
/>
);
});
(A key was added here in case there are more than one instance of a house object)
You can simply write.
<img src={this.states.results.address.type==="house"?house.attribute.photo : otherwise_photo}/>
Basically this would compare address.type is house or not,then return the result corresponded.
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}`);
}
});
I am trying to add local json data to a GeoJson layer in Leaflet, and then (for now) bind a popup to each feature in the json. The trouble is that I am unable to first create a geojson layer, and then later bind popups. Is there any way to do this? I am only able to create the layer and add the popups at the same time. What I have so far:
Create the map.
map = new L.Map('map');
Grab the local json file:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"name": "Denver",
"amenity": "Baseball Stadium",
"popupContent": "This is where the Rockies play!"
},
"geometry": {
"type": "Point",
"coordinates": [-102.99404, 37.75621]
}
},
{
"type": "Feature",
"properties": {
"name": "Baltimore",
"amenity": "Baseball Stadium",
"popupContent": "This is where the Orioles play!"
},
"geometry": {
"type": "Point",
"coordinates": [-76.6167, 39.2833]
}
}
]
}
and send json through to plotData():
function plotData( data )
{
var pointLayer = L.geoJson().addTo(map);
// 1. works
L.geoJson(data, {
onEachFeature: onEachFeature
}).addTo(map);
// 2. does not bind popups
pointLayer.addData( data, {
onEachFeature: onEachFeature
}
);
// 3. Error - invalid GeoJson Object
pointLayer.addData( L.geoJson(data, {
onEachFeature: onEachFeature
})
);
}
function onEachFeature( feature, layer )
{
layer.bindPopup( feature.properties.name );
}
The markers display just fine on the map for scenario 1 and 2 (with 1 also displaying popups). Now, is there any reason why I should not be trying to first create the layer and then bind actions to the features? Is it better practice to just do what I have stated in 1?
The third option won't work, because you're feeding L.Layer object where a GeoJSON object should go. L.GeoJSON.addData() function does not have onEachFeature parameter. Basically, when you have processed a GeoJSON, its feature properties are gone.
There are two ways to proceed.
// create empty GeoJSON layer
var pointLayer = L.geoJson(null, { onEachFeature: storeName }).addTo(map);
// add data to it later, invoking storeName() function
pointLayer.addData(data);
// which stores names
function storeName(f, l) { l._gname = f.properties.name; }
// and when you're ready...
pointLayer.eachLayer(addPopupFromGName);
// add popups with stored name
function addPopupFromGName(l) { l.bindPopup(l._gname); }
Or just add onEachFeature function to L.GeoJSON layer options:
var pointLayer = L.geoJson(null, { onEachFeature: onEachFeature }).addTo(map);
I currently have to code below and a static json file. However how can I set my model defaults to the data in the json file? My JSON file has a few pages - I want to be able to get defaults and set defaults.
var PageModel = Backbone.Model.extend({
initialize: function () {
console.log('initiliazed model');
},
url: "data/data.json",
defaults: function() {
return PageView.defaultsFromJSON;
}
});
var PageView = Backbone.View.extend ({
initialize: function () {
console.log('initiliazed view')
_.bindAll(this);
this.model.fetch();
this.render();
this.model.on('change',this.render);
},
el : '#ev-wrapper',
render: function () {
$('#ev-wrapper').append(Handlebars.compile($('#ev-template').html())(this.model.toJSON()));
$('.ev-asset-loader').fadeOut('slow', function (event) {
this.remove();
});
}
});
pageModel = new PageView({model: new PageModel()});
json file -
{
"page":[{
"id":"p05",
"title":"ptitle1",
"text":"pinitialtext"
},
{
"id":"p10",
"title":"ptitle2",
"text":"pinitialtext"
}]
}
Are you rendering the page with a server-side language ? If yes, inject a JSON string into the view containing your defaults, and fill your model with it.
var data = <?php echo $json ?>,
model = new PageModel(data),
view = new PageView({model: model, el : $('#ev-wrapper')[0]});
If you are not using a server-side language, I think you could issue an AJAX request with JQuery to load your JSON data, but this would be the same as calling fetch.
I can't see a way to "include" the JSON file another way.
I am trying to solve a similar problem (Populating Backbone models from a static JSON file for a demo).
I came across an example on the Backbone.Leaflet library:
https://github.com/LuizArmesto/backbone.leaflet/blob/master/examples/map.html
// This isn't the backbone way, but we want to keep this example
// as simple as possible.
$( '#render' ).click( function () {
geoCollection.reset( JSON.parse( $( '#geoJSON' ).val() ) );
});
In this example, the ID in question (#geoJSON) is a text area that houses the JSON the author (LuizArmesto) is trying to load into the model.
<textarea id="geoJSON">
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [[[-46.6155, -23.5023], [-46.6193, -23.5030], [-46.6247, -23.5073], [-46.6252, -23.5117], [-46.6218, -23.5115], [-46.6154, -23.5080], [-46.6150, -23.5037], [-46.6155, -23.5023]]]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [[-46.6318, -23.4900], [-46.6256, -23.4916], [-46.6200, -23.4900], [-46.6100, -23.4900]]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [-46.6368, -23.5100]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [-46.6156, -23.5016]
},
"properties": {}
}
]
}
</textarea>
As stated in his comments, this isn't idiomatic of backbone (or "the backbone way"), but it works great for little side projects that don't need a server.