Accessing variables in a JSON? - javascript

I'm currently working with the Bing Isochrone Api. I set up my http request in Angular using the HTTPClient. This is the example of the data set I get back:
{
"authenticationResultCode": "ValidCredentials",
"brandLogoUri": "http:\/\/dev.virtualearth.net\/Branding\/logo_powered_by.png",
"copyright": "Copyright © 2018 Microsoft and its suppliers. All rights reserved. This API cannot be accessed and the content and any results may not be used, reproduced or transmitted in any manner without express written permission from Microsoft Corporation.",
"resourceSets": [{
"estimatedTotal": 1,
"resources": [{
"__type": "IsochroneResponse:http:\/\/schemas.microsoft.com\/search\/local\/ws\/rest\/v1",
"origin": {
"latitude": 47.640068,
"longitude": -122.129858
},
"polygons": [{
"coordinates": [
[
[48.22848, -122.12867],
[48.22613, -122.10625],
[48.229309, -122.08228],
[48.23733, -122.07666],
[48.24474, -122.05325],
[48.24469, -122.0532],
[48.24424, -122.05386],
[48.23119, -122.06654],
[48.22848, -122.12867]
]
]
}]
}]
}],
"statusCode": 200,
"statusDescription": "OK",
"traceId": "4ed97517798141a1b5bb9df40509f190|CO30305304|7.7.0.0|"
}
I can get to the resourceSets with this
this
.http
.get(`http://dev.virtualearth.net/REST/v1/Routes/Isochrones?waypoint=\
${this.testPointlat},${this.testPointlong}&maxTime=15&timeUnit=Minutes\
&dateTime=2017-11-27T18:00:00-08:00&travelMode=Driving\
&key=$$$$$$$$$$$$$
`).subscribe(
(response) => {
this.driveTimeCoords = response.resourceSets;
console.log(this.driveTimeCoords);
const polygons = this.driveTimeCoords.resources.polygons;
console.log(polygons);
}
);
})
So this.driveTimeCoords gives me an array... My attempt after it doesn't work obviously as it says undefined. Would i do a .foreach with an if or something? I'm probably overthinking this. All I want are the coordinates so I can then .map() them into a geojson featuregroup for leaflet.
Thanks!
Edit:
On console.log this.driveTimeCoords I get
[{…}]0: estimatedTotal: 1resources: [{…}]

Your JSON formatting is off: note how resourceSets, resources and polygons are object arrays, meaning you need to call the array's index to access the data, like so:
this.driveTimeCoords = response.resourceSets[0];
console.log(this.driveTimeCoords);
const polygons = this.driveTimeCoords.resources[0].polygons[0];
console.log(polygons);
To fix this issue, your JSON should be formatted like this:
{
"authenticationResultCode": "ValidCredentials",
"brandLogoUri": "http:\/\/dev.virtualearth.net\/Branding\/logo_powered_by.png",
"copyright": "Copyright © 2018 Microsoft and its suppliers. All rights reserved. This API cannot be accessed and the content and any results may not be used, reproduced or transmitted in any manner without express written permission from Microsoft Corporation.",
"resourceSets": {
"estimatedTotal": 1,
"resources": {
"__type": "IsochroneResponse:http:\/\/schemas.microsoft.com\/search\/local\/ws\/rest\/v1",
"origin": {
"latitude": 47.640068,
"longitude": -122.129858
},
"polygons": {
"coordinates": [
{"latitude": 48.22848, "longitude": -122.12867},
{"latitude": 48.22613, "longitude": -122.10625},
{"latitude": 48.229309, "longitude": -122.08228},
{"latitude": 48.23733, "longitude": -122.07666},
{"latitude": 48.24474, "longitude": -122.05325},
{"latitude": 48.24469, "longitude": -122.0532},
{"latitude": 48.24424, "longitude": -122.05386},
{"latitude": 48.23119, "longitude": -122.06654},
{"latitude": 48.22848, "longitude": -122.12867}
]
}
}
},
"statusCode": 200,
"statusDescription": "OK",
"traceId": "4ed97517798141a1b5bb9df40509f190|CO30305304|7.7.0.0|"
}
I added variable names to the coordinates, for easier comprehension of the data being read.

Judging by your JSON object, it looks like this.driveTimeCoords which is a reference to the resourceSets in your JSON, is an array, which, for every property you seem to want (resource, polygons, coordinates) all successively are arrays as well. Thus, you must do a sequence of nested .map() operations.
Try the following:
var result = this.driveTimeCoords.map((obj)=>{
return obj.resources.map((resource)=>{
return resource.polygon.map((poly)=> poly.coordinates )
})
})
Doing this, makes it so that, if any of those arrays contain multiple references, you'd get them all. Afterwards, you could flatten the array, or simply reference the first one as another guy suggested result[0][0][0]

Seeing as they are arrays, you need to access via thier index:
let json = {
"authenticationResultCode": "ValidCredentials",
"brandLogoUri": "http:\/\/dev.virtualearth.net\/Branding\/logo_powered_by.png",
"copyright": "Copyright © 2018 Microsoft and its suppliers. All rights reserved. This API cannot be accessed and the content and any results may not be used, reproduced or transmitted in any manner without express written permission from Microsoft Corporation.",
"resourceSets": [{
"estimatedTotal": 1,
"resources": [{
"__type": "IsochroneResponse:http:\/\/schemas.microsoft.com\/search\/local\/ws\/rest\/v1",
"origin": {
"latitude": 47.640068,
"longitude": -122.129858
},
"polygons": [{
"coordinates": [
[
[48.22848, -122.12867],
[48.22613, -122.10625],
[48.229309, -122.08228],
[48.23733, -122.07666],
[48.24474, -122.05325],
[48.24469, -122.0532],
[48.24424, -122.05386],
[48.23119, -122.06654],
[48.22848, -122.12867]
]
]
}]
}]
}],
"statusCode": 200,
"statusDescription": "OK",
"traceId": "4ed97517798141a1b5bb9df40509f190|CO30305304|7.7.0.0|"
}
let polys = json['resourceSets'][0].resources[0].polygons;
let o = document.getElementById('output');
o.innerHTML = JSON.stringify(polys);
<div id="output"></div>

With this formating you can acces coordinate with these paths :
.resourceSets[0].resources[0].polygons[0].coordinates[0][0][0] = 48.22848
.resourceSets[0].resources[0].polygons[0].coordinates[0][0][1] = -122.12867
.resourceSets[0].resources[0].polygons[0].coordinates[0][1][0] = 48.22613
.resourceSets[0].resources[0].polygons[0].coordinates[0][1][1] = -122.10625
.resourceSets[0].resources[0].polygons[0].coordinates[0][2][0] = 48.229309
.resourceSets[0].resources[0].polygons[0].coordinates[0][2][1] = -122.08228
.resourceSets[0].resources[0].polygons[0].coordinates[0][3][0] = 48.23733
.resourceSets[0].resources[0].polygons[0].coordinates[0][3][1] = -122.07666
.resourceSets[0].resources[0].polygons[0].coordinates[0][4][0] = 48.24474
.resourceSets[0].resources[0].polygons[0].coordinates[0][4][1] = -122.05325
.resourceSets[0].resources[0].polygons[0].coordinates[0][5][0] = 48.24469
.resourceSets[0].resources[0].polygons[0].coordinates[0][5][1] = -122.0532
.resourceSets[0].resources[0].polygons[0].coordinates[0][6][0] = 48.24424
.resourceSets[0].resources[0].polygons[0].coordinates[0][6][1] = -122.05386
.resourceSets[0].resources[0].polygons[0].coordinates[0][7][0] = 48.23119
.resourceSets[0].resources[0].polygons[0].coordinates[0][7][1] = -122.06654
.resourceSets[0].resources[0].polygons[0].coordinates[0][8][0] = 48.22848
.resourceSets[0].resources[0].polygons[0].coordinates[0][8][1] = -122.12867

Related

How do I map JSON data that is passed into a function?

Im trying to take JSON data and pass it into my 'HistoryChart' Component to try and map the dates and prices into two arrays so that I can present them on my chart. However, I keep getting undefined errors.
Here is the JSON Data:
{
"_id": 1,
"name": "",
"brand": "",
"image": "",
"sources": [],
"history": [
{
"_id": 3,
"price": "299.99",
"product": 1,
"date": "2021-07-01"
},
{
"_id": 4,
"price": "399.99",
"product": 1,
"date": "2021-07-08"
},
{
"_id": 5,
"price": "499.99",
"product": 1,
"date": "2021-07-15"
},
{
"_id": 6,
"price": "599.99",
"product": 1,
"date": "2021-07-22"
},
{
"_id": 7,
"price": "699.99",
"product": 1,
"date": "2021-07-29"
}
]
}
Here is my HistoryChart Component:
function HistoryChart({product}) {
var dates = product.history.map(function(e){ //<-- The Problem lies here where it says cannot map undefined.
return e.date;
});
var prices = product.history.map(function(e){
return e.price;
});
return (
<div>
<Line
data={{
labels: dates,
datasets: [{
label: `Average Price History (ID: ${product._id})`, //<-- This part works
backgroundColor:/* 'transparent' */ '#00ad0e',
borderColor: '#00ad0e',
data: prices,
}]
}}
width={100}
height={50}
options={{ maintainAspectRatio: true }}
/>
</div>
)
}
I am also using redux to get the Data:
const productDetails = useSelector(state => state.productDetails)
const {error, loading, product} = productDetails
And the data is passed into the HistoryChart Component like this:
<HistoryChart product={product}/>
Any Help would be Much appreciated, Thanks.
Sorry if this is not your principal problem, but same time when .map resulting in undefined the most simple adjust is verify if your array is undefined.
So in my projects i always check first if array is undefined, i will use your code to do a example
function HistoryChart({product}) {
if (product !== undefined){
var dates = product.history.map(function(e){
return e.date;
});
var prices = product.history.map(function(e){
return e.price;
});
}
Try this aproach and let me know if this work.
Cause of Error
As the data come from server, it take some time to load. and you get the undefine error because 1st time you want to access history of object product which is not yet loaded successfully.
Solution
const price = product && product.history.map(//do what you want)
use key values of object this way not cause any error because if product is not loaded it does'nt call map function and when product object loaded successfully it will call map function

How to loop through JSON

I am trying to loop through this JSON in order to get to the 'name' parameter. The data comes from Microsoft's Bing API. I can pass in coordinates to get the name of a place. I have pasted the response below. as well as my attempt. Please assist.
{
"authenticationResultCode":"ValidCredentials",
"brandLogoUri":"http://dev.virtualearth.net/Branding/logo_powered_by.png",
"copyright":"Copyright © 2018 Microsoft and its suppliers. All rights reserved. This API cannot be accessed and the content and any results may not be used, reproduced or transmitted in any manner without express written permission from Microsoft Corporation.",
"resourceSets":[
{
"estimatedTotal":1,
"resources":[
{
"__type":"Location:http://schemas.microsoft.com/search/local/ws/rest/v1",
"bbox":[
47.636677282429325,
-122.13698331308882,
47.64440271757068,
-122.12169668691118
],
"name":"1 Microsoft Way, Redmond, WA 98052",
"point":{
"type":"Point",
"coordinates":[
47.64054,
-122.12934
]
},
"address":{
"addressLine":"1 Microsoft Way",
"adminDistrict":"WA",
"adminDistrict2":"King Co.",
"countryRegion":"United States",
"formattedAddress":"1 Microsoft Way, Redmond, WA 98052",
"locality":"Redmond",
"postalCode":"98052"
},
"confidence":"Medium",
"entityType":"Address",
"geocodePoints":[
{
"type":"Point",
"coordinates":[
47.64054,
-122.12934
],
"calculationMethod":"Interpolation",
"usageTypes":[
"Display",
"Route"
]
}
],
"matchCodes":[
"Good"
]
}
]
}
],
"statusCode":200,
"statusDescription":"OK",
"traceId":"089a91ac5b694010884d6a7b7d245718|CH12F221B8|7.7.0.0|CH1AAPBD7C89012"
}
I have tried the following but am getting a length undefined error:
this.http.get('http://dev.virtualearth.net/REST/v1/Locations/'+this.latitude+','+this.longitide+'?o=json&key=AgThwaQToIr5UwjAisaBegjG3qpxBfgFL354mlTxiRPGOrqId8nShnugy40jpebW').subscribe(data => {
this.place = data;
for(var i; i < this.place.resourceSets.length; i++){
this.dataset = this.place.resourceSets[i].resources;
console.log(this.dataset);
}
})
}
I think a big part of your problem is you're using this for your local variable assignments. Ideally you should use let but for backwards compatible browsers you can always use var.
See below, especially the loop, which performs var dataset and also caches the length to the variable n:
var place = {
"authenticationResultCode": "ValidCredentials",
"brandLogoUri": "http://dev.virtualearth.net/Branding/logo_powered_by.png",
"copyright": "Copyright © 2018 Microsoft and its suppliers. All rights reserved. This API cannot be accessed and the content and any results may not be used, reproduced or transmitted in any manner without express written permission from Microsoft Corporation.",
"resourceSets": [{
"estimatedTotal": 1,
"resources": [{
"__type": "Location:http://schemas.microsoft.com/search/local/ws/rest/v1",
"bbox": [
47.636677282429325, -122.13698331308882,
47.64440271757068, -122.12169668691118
],
"name": "1 Microsoft Way, Redmond, WA 98052",
"point": {
"type": "Point",
"coordinates": [
47.64054, -122.12934
]
},
"address": {
"addressLine": "1 Microsoft Way",
"adminDistrict": "WA",
"adminDistrict2": "King Co.",
"countryRegion": "United States",
"formattedAddress": "1 Microsoft Way, Redmond, WA 98052",
"locality": "Redmond",
"postalCode": "98052"
},
"confidence": "Medium",
"entityType": "Address",
"geocodePoints": [{
"type": "Point",
"coordinates": [
47.64054, -122.12934
],
"calculationMethod": "Interpolation",
"usageTypes": [
"Display",
"Route"
]
}],
"matchCodes": [
"Good"
]
}]
}],
"statusCode": 200,
"statusDescription": "OK",
"traceId": "089a91ac5b694010884d6a7b7d245718|CH12F221B8|7.7.0.0|CH1AAPBD7C89012"
}
for (var i=0,n=place.resourceSets.length; i<n; i++) {
var dataset = place.resourceSets[i].resources;
console.log(dataset);
}
You can try the below code for your question :--
<!DOCTYPE html>
<html>
<head>
<title></title>
<script type="text/javascript">
var text = '{ "data":{"rule":[{"clauses":{ "id":"q", "act":"the", "r":"1","cond":"2"}, "data":{"cond_oper":"7"}},{"clauses":{"id":"qw","act":"thefir","r":"1","cond":"1"},"data":{ "cond_oper":"7"}}]}}';
var obj = JSON.parse(text);
console.log(obj.data.rule.length);
alert(obj.data.rule.length);
//Get the count
// var count = obj.data.rule.length
for(var i=0; i<obj.data.rule.length; i++)
{
alert(obj.data.rule[i].clauses.id);
console.log(obj.data.rule[i].clauses.id)
}
</script>
</head>
<body>
</body>
</html>
Your issue is the var i;, i is not being initialized only declared. Initializing i with = 0 this works fine locally for me using a sample lat/long.
$.get('http://dev.virtualearth.net/REST/v1/Locations/47.640568390488625,-122.1293731033802?o=json&key=AgThwaQToIr5UwjAisaBegjG3qpxBfgFL354mlTxiRPGOrqId8nShnugy40jpebW',function(data){
this.place = data;
console.log(this.place.resourceSets.length);
for(var i = 0; i < this.place.resourceSets.length; i++){
console.log(this.place.resourceSets[0]);
}
});
});

How to parse a JSON array string in JavaScript?

I have an JSON array like this
var filter_value_data = [{"Status":[{"name":"Open","id":"1"},{"name":"Pending","id":"2"},{"name":"Resolved","id":"3"},{"name":"Closed","id":"4"},{"name":"Evaluation","id":"5"}]},{"Payment Status":[{"name":"Paid","id":"10"},{"name":"UnPaid","id":"11"},{"name":"Part Paid","id":"12"}]},{"Priority":[{"name":"Low","id":"6"},{"name":"Medium","id":"7"},{"name":"High","id":"8"},{"name":"Urgent","id":"9"}]}]
I have tried filter_value_data["Status"] which is obviously wrong. How do I get the JSON elements for Status using the names like Status,Payment Status?
filter_value_data is an array (having []), so use filter_value_data[0].Status to get the first element-object with property "Status".
It is always good to format your code in order to see the hierarchy of the structures:
var filter_value_data = [
{
"Status": [
{
"name": "Open",
"id": "1"
}, {
"name": "Pending",
"id": "2"
}, ...
]
}, {
"Payment Status": [
{
"name": "Paid",
"id": "10"
}, ...
]
}, {
"Priority": [
{
"name": "Low",
"id": "6"
}, ...
]
}
];
With your current JSON you can't get the elements with the name alone.
You can get Status with filter_value_data[0]['Status'] and Payment status with filter_value_data[1]['Payment Status'].
This is because the keys are in seperate objects in the array.
In order to get them with filter_value_data['Status'] you need to change your JSON to
var filter_value_data = {
"Status":[
{"name":"Open","id":"1"},
{"name":"Pending","id":"2"},
{"name":"Resolved","id":"3"},
{"name":"Closed","id":"4"},
{"name":"Evaluation","id":"5"}
],
"Payment Status":[
{"name":"Paid","id":"10"},
{"name":"UnPaid","id":"11"},
{"name":"Part Paid","id":"12"}
],
"Priority":[
{"name":"Low","id":"6"},
{"name":"Medium","id":"7"},
{"name":"High","id":"8"},
{"name":"Urgent","id":"9"}
]
};
I wrote this on my phone so it's not as well-formatted as usual. I'll change it ASAP.
With your current JSON, created a result which might be helpful for you.
JS:
$.each(filter_value_data,function(ind,val){
var sta = val.Status; // Status Object get displayed
for(var i=0;i<sta.length;i++){
var idVal= sta[i].id;
var nameVal = sta[i].name;
Statusarray.push(idVal,nameVal);
console.log(Statusarray);
}
})
FiddleDemo
You can use below code, it will return status object
filter_value_data[0]['Status']
filter_value_data[0]['Payment Status']
to get Single value you use :
filter_value_data[0]['Status'][0]['name']

search partial match in an array

I have a long Array like this:
var wifiArr = {
"results": {
"fields": [
"Name",
"Address",
"Suburb",
"Latitude",
"Longitude"
],
"rows": [
{
"Name": "7th Brigade Park, Chermside",
"Address": "Delaware St",
"Suburb": "Chermside",
"Latitude": -27.37893,
"Longitude": 153.04461
},
.
. total 55 of those
.
{
"Name": "Annerley Library Wifi",
"Address": "450 Ipswich Road",
"Suburb": "Annerley, 4103",
"Latitude": -27.50942285,
"Longitude": 153.0333218
},
]
}
}
I'm trying to find every 'Name', 'suburb' or 'address' which contains for example 'ann' in it's name and return with the index of those items, relative to 'rows' .. Just so I can access to all details later on by using
var wifis = wifiArr.results.rows;
// returned index
console.log(wifis[index].Latitude);
I tried few different things but none of them worked as I wanted (usually they just give single index). The only thing I can use is plain Javascript and jQuery. No other libraries (as others recommended me before).
I would appreciate all the help, Thanks
So, if you can use jQuery then you can give a try with jQuery.grep. And in your code
arr = jQuery.grep(wifiArr.results.rows, function(row, index) {
return row.Name.indexOf('ann') > -1
|| row.Address.indexOf('ann') > -1
|| row.Suburb.indexOf('ann') > -1;
});
Here is an example http://jsfiddle.net/ry5AC/1/
Also, if you support newer browsers, you can use filter function. Related article on MDN. It is invoked with index argument ;)

Javascript Array Object iteration of properties

After reading many Stackoverflow questions, blogs, and documentation I still cannot figure out why this particular iteration over any array is not working.
I am using jQuery and javascript(obviously) to pull a GeoJSON file and then going over the properties of the resulting object to pull desired key/value pairs. As I find those pairs I want to insert then into another array object. The object is created as I expected however when I attempt to go over the newly created object nothing happens and if I try to find its length it returns a length of 0.
This is where I pull the records:
_recordsFromGeoJSON: function(inputText) {
var retRecords = {},
$.getJSON(this.GeoJSONUrl, function(data) {
var geoJSONdata = data;
$.each(geoJSONdata.features, function(fkey, fvalue) {
$.each(fvalue.properties, function(pkey, pvalue) {
var re = new RegExp(inputText, "i");
var retest = re.test(pvalue);
if (retest) {
retRecords[pvalue] = fvalue.geometry.coordinates;
return;
}
});
});
});
return retRecords;
},
This is the code for the interation over the new object:
for(var key in this._retRecords) {
//this function will never run
var always = foo(bar);
}
Some sample GeoJSON:
{
"type": "FeatureCollection",
"features": [
{ "type": "Feature", "id": 0, "properties": { "NAME": "14 PARK PLACE PH 4", "AREAID": 3.0, "STR12M": 0.0, "CLS12M": 6.0, "STR4M": 0.0, "CLS4M": 0.0, "TOTAL": 164.0, "OCC": 112.0, "NFU": 0.0, "UNC": 3.0, "DVL": 49.0, "UDVL": 0.0 }, "geometry": { "type": "Point", "coordinates": [ -93.27512816536759, 37.044305883435001 ] } }
,
{ "type": "Feature", "id": 1, "properties": { "NAME": "ALPHA MEADOWS NORTH", "AREAID": 8.0, "STR12M": 0.0, "CLS12M": 0.0, "STR4M": 0.0, "CLS4M": 0.0, "TOTAL": 12.0, "OCC": 0.0, "NFU": 0.0, "UNC": 0.0, "DVL": 0.0, "UDVL": 0.0 }, "geometry": { "type": "Point", "coordinates": [ -92.839131163095786, 37.119205483765143 ] } }
]
}
When I console.log(this._retRecords); Chrome reports shows the object with all the properties I expected from the dataset:
Object
14 PARK PLACE PH 4: Array[2]
0: -93.27512816536759
1: 37.044305883435
length: 2
__proto__: Array[0]
ALPHA MEADOWS NORTH: Array[2]
0: -92.839131163095786
1: 37.119205483765143
length: 2
__proto__: Array[0]
Using both methods given on this question report 0 length.
I am quite certain I am missing something fundamental but I cannot find what it is. Any help, criticism, alternative methods would be great!
It appears that you don't understand that your getJSON() function starts immediately (e.g. sends the request) and then returns immediately long before the getJSON function has completed it's work. It's work will be done sometime later when the completion function is called. Thus retRecords is not yet populated when the _recordsFromGeoJSON() function returns.
This is asynchronous programming. The completion function for getJSON will be called sometime LATER, long after _recordsFromGeoJSON() returns. Thus, you cannot treat it like synchronous, serial programming.
Instead, retRecords is only known in the completion function or in any function you pass the data to and call from that completion function. This is how asynchronous programming works in javascript. You must initiate all further processing of the getJSON() result from the completion function. And, you can't return the result from _recordsFromGeoJSON() because the result is not yet known when that function returns. This is a different way of coding and it a bit of a pain, but it is how you have to deal with asynchronous operations in javascript.

Categories