Unexpected empty key-value in JSON string - javascript

I'm trying to parse a json string embedded in my html file.
Here is the reduced code.
<html>
<head>
<script src="./jquery-1.4.4.min.js" type="text/javascript"></script>
<script>
function parse_json(){
var jtext = $("#mtxt").text();
var jdata = jQuery.parseJSON(jtext);
JSON.parse(JSON.stringify(jdata), function (key, value){
alert("key=" + key + " value=" + value);
if(key== ""){
alert("value in string" + JSON.stringify(value));
}
});
}
$(document).ready(function() {
$("#run").click( function () {
parse_json();
});
});
</script>
</head>
<body>
<a id="run" href="#">run</a>
<div id="mtxt">
{"caller": "539293493"}
</div>
</body>
</html>
When I parse it, apart from the expected "caller" value, I get an extra empty "key" and "value".
The first alert gives me
key= value=[object Object]
The second alert gives me
value in string{}
What is happening? Why this extra entry?

Ok, you're passing the second param to JSON.parse() which is the reviver callback. Per the JSON docs, This callback is executed "...for every key and value at every level of the final result. Each value will be replaced by the result of the reviver function. This can be used to reform generic objects into instances of pseudoclasses, or to transform date strings into Date objects."
Since your reviver callback doesn't return anything, your object is getting improperly manipulated and distorted. I don't believe you have any use for the reviver in your use here. I have never seen it in use anywhere, and I use JSON.parse a LOT.
Your code should look like this:
function parse_json()
{
var jtext = $("#mtxt").text(),
jdata = JSON.parse( $.trim( jtext ) ),
key,
value;
for( key in jdata )
{
if( Object.prototype.hasOwnProperty.call( jdata, key ) )
{
value = jdata[key];
//prefer console.log here...
alert( 'key: ' + key + ', value: ' + value)
}
}
}
$( function()
{
$( '#run' ).click( function()
{
parse_json();
} );
} );
Demo: http://jsfiddle.net/hjVqf/

Ok, I've been fooling around with this on jsfiddle. One of the things I noticed that you weren't doing, was returning a value for the reviver function. According to the Microsoft JSON.parse docs, the point of the function is to return a modified (if necessary) version of the value property which will update the DOM object. Now, it also says that:
A function that filters and transforms
the results. The deserialized object
is traversed recursively, and the
reviver function is called for each
member of the object in post-order
(every object is revived after all its
members have been revived).
Ok, so I think the key here is that the reason the function is run twice, is because it's running for the first member (simply "caller": "539293493") and then for the object itself ({"caller": "539293493"}).
You'll notice that in my linked example, with the added return value; statement, the object with the blank key is the whole object.

Related

Complex JSON obj and jQuery or Javascript map to specific key, value

I am banging my head trying to figure this out. And it should not be this hard. I am obviously missing a step.
I am pulling data from: openaq.org
The object I get back is based on a JSON object.
For now, I am using jQuery to parse the object and I am getting to the sub portion of the object that hold the specific parameter I want but I can't get to the specific key,value pair.
The object does not come back in the same order all the time. So when I tried to originally set up my call I did something like
obj.results.measurements[0].
Well since the obj can come back in an random order, I went back to find the key,value pair again and it was the wrong value, throwing my visual off.
That said, I have looked at use jQuery's find() on JSON object and for some reason can not get what I need from the object I am given by openaq.org.
One version of the object looks like this:
{"meta":{"name":"openaq-api","license":"CC BY 4.0d","website":"https://u50g7n0cbj.execute-api.us-east-1.amazonaws.com/","page":1,"limit":100,"found":1},"results":[{"location":"Metro Lofts","city":null,"country":"US","coordinates":{"latitude":39.731,"longitude":-104.9888},"measurements":[{"parameter":"pm10","value":49.9,"lastUpdated":"2021-08-09T20:49:38+00:00","unit":"µg/m³"},{"parameter":"pm1","value":24,"lastUpdated":"2021-08-09T20:49:38+00:00","unit":"µg/m³"},{"parameter":"um100","value":0,"lastUpdated":"2021-08-09T20:49:38+00:00","unit":"particles/cm³"},{"parameter":"um025","value":0.28,"lastUpdated":"2021-08-09T20:49:38+00:00","unit":"particles/cm³"},{"parameter":"um010","value":4.1,"lastUpdated":"2021-08-09T20:49:38+00:00","unit":"particles/cm³"},{"parameter":"pm25","value":41.1,"lastUpdated":"2021-08-09T20:49:38+00:00","unit":"µg/m³"}]}]}
I am trying to get the "pm25" value.
The code I have tried is this:
function getAirQualityJson(){
$.ajax({
url: 'https://api.openaq.org/v2/latest?coordinates=39.73915,-104.9847',
type: 'GET',
dataType: "json"
// data: data ,
}).done(function(json){
console.log("the json is" + JSON.stringify(json));
console.log("the json internal is" + JSON.stringify(json.results));
var obj = json.results;
var pm25 = "";
//console.log(JSON.stringify(json.results.measurements[0]["parameter"]));
$.each(json.results[0], function(i,items){
//console.log("obj item:" + JSON.stringify(obj[0].measurements));
$.each(obj[0].measurements, function(y,things){
//console.log("each measurement:" + JSON.stringify(obj[0].measurements[0].value));//get each measurement
//pm 2.5
//Can come back in random order, get value from the key "pm25"
// pm25 = JSON.stringify(obj[0].measurements[2].value);
pm25 = JSON.stringify(obj[0].measurements[0].value);
console.log("pm25 is: " + pm25); // not right
});
});
//Trying Grep and map below too. Not working
jQuery.map(obj, function(objThing)
{ console.log("map it 1:" + JSON.stringify(objThing.measurements.parameter));
if(objThing.measurements.parameter === "pm25"){
// return objThing; // or return obj.name, whatever.
console.log("map it:" + objThing);
}else{
console.log("in else for pm25 map");
}
});
jQuery.grep(obj, function(otherObj) {
//return otherObj.parameter === "pm25";
console.log("Grep it" + otherObj.measurements.parameter === "pm25");
});
});
}
getAirQualityJson();
https://jsfiddle.net/7quL0asz/
The loop is running through I as you can see I tried [2] which was the original placement of the 'pm25' value but then it switched up it's spot to the 3rd or 4th spot, so it is unpredictable.
I tried jQuery Grep and Map but it came back undefined or false.
So my question is, how would I parse this to get the 'pm25' key,value. After that, I can get the rest if I need them.
Thank you in advance for all the help.
You can use array#find and optional chaining to do this,
because we are using optional chaining, undefined will be returned if a property is missing.
Demo:
let data = {"meta":{"name":"openaq-api","license":"CC BY 4.0d","website":"https://u50g7n0cbj.execute-api.us-east-1.amazonaws.com/","page":1,"limit":100,"found":1},"results":[{"location":"Metro Lofts","city":null,"country":"US","coordinates":{"latitude":39.731,"longitude":-104.9888},"measurements":[{"parameter":"pm10","value":49.9,"lastUpdated":"2021-08-09T20:49:38+00:00","unit":"µg/m³"},{"parameter":"pm1","value":24,"lastUpdated":"2021-08-09T20:49:38+00:00","unit":"µg/m³"},{"parameter":"um100","value":0,"lastUpdated":"2021-08-09T20:49:38+00:00","unit":"particles/cm³"},{"parameter":"um025","value":0.28,"lastUpdated":"2021-08-09T20:49:38+00:00","unit":"particles/cm³"},{"parameter":"um010","value":4.1,"lastUpdated":"2021-08-09T20:49:38+00:00","unit":"particles/cm³"},{"parameter":"pm25","value":41.1,"lastUpdated":"2021-08-09T20:49:38+00:00","unit":"µg/m³"}]}]}
let found = data?.results?.[0]?.measurements?.find?.(
({ parameter }) => parameter === "pm25"
);
console.log(found);
You can iterate over measurements and find the object you need:
const data = '{"meta":{"name":"openaq-api","license":"CC BY 4.0d","website":"https://u50g7n0cbj.execute-api.us-east-1.amazonaws.com/","page":1,"limit":100,"found":1},"results":[{"location":"Metro Lofts","city":null,"country":"US","coordinates":{"latitude":39.731,"longitude":-104.9888},"measurements":[{"parameter":"pm10","value":49.9,"lastUpdated":"2021-08-09T20:49:38+00:00","unit":"µg/m³"},{"parameter":"pm1","value":24,"lastUpdated":"2021-08-09T20:49:38+00:00","unit":"µg/m³"},{"parameter":"um100","value":0,"lastUpdated":"2021-08-09T20:49:38+00:00","unit":"particles/cm³"},{"parameter":"um025","value":0.28,"lastUpdated":"2021-08-09T20:49:38+00:00","unit":"particles/cm³"},{"parameter":"um010","value":4.1,"lastUpdated":"2021-08-09T20:49:38+00:00","unit":"particles/cm³"},{"parameter":"pm25","value":41.1,"lastUpdated":"2021-08-09T20:49:38+00:00","unit":"µg/m³"}]}]}';
const json = JSON.parse(data);
let value = null;
const measurements = json?.results?.[0]?.measurements ?? null;
if(measurements)
for (const item of measurements)
if (item.parameter === 'pm25') {
value = item.value;
break;
}
if (value) {
// here you can use the value
console.log(value);
}
else {
// here you should handle the case where 'pm25' is not found
}

How to append function with object as a parameter in javascript string?

<script>
//some code here
var content = '<div onclick="populatedata(\'' + obj.Records[t] + '\')" >';
function populatedata(obj) {
console.log(typeof obj);
}
</script>
Now output of the above code is string, but I want object content in function populatedata.
As #nnnnnn Suggested I had passed index of record in function and received it in populatedata.
<script>
//some code here
var content = "<div onclick="populatedata("+t+")>";
function populatedata(index) {
console.log(obj.Records[index]); //this is just for illustration
//further processing here
}
</script>
You didn't clarify what type obj.Records[t] is, but I guess it is an object. So you have problem because result of concatenation with a String is always a new string, with toString() applied to non-string types (obj.Records[t] in your case).
What you need to do is to stringify your object manually so that you control string presentation yourself:
var content = '<div onclick="populatedata(' + JSON.stringify(obj.Records[t]) + ')">';
Then result of such concatenation would be something like (if obj.Records[t] = {name: 123}):
<div onclick="populatedata({"name":123})">
which will allow populatedata invocation with proper parameter.
If you want to be able to further process the argument of populatedata, you'll first want to stringify it, then change your function from logging the typeof to just the object.
var content = "<div onclick='populatedata(" + JSON.stringify(obj.Records[t]) + ")'>test</div>";
function populatedata(obj) {
// do things with obj here
console.log(obj);
}
However, as Oriol mentioned in a comment on your question, you probably don't want to take that approach. It's better to:
Manage handlers through the dom API
Pass data objects in programmatically as opposed to embedding them into the dom

AJAX & Json get function with jQuery

I am creating a "Garment checker" using ajax and I would like the user to put the ID into the input followed by a request to the URL. which prints out the code if it exists. The code below just isn't doing the job as I would like it to although I think that it is almost correct. Can anybody see my mistakes or point me in the right direction please?
<script type="text/javascript">
//<![CDATA[
$(document).ready(function() {
"use strict";
$('#lookupForm')
.removeAttr('onsubmit')
.submit(function(event) {
event.preventDefault();
var target = document.getElementById('garmentID');
if(target.value.length > 0) {
fetchData(target.value);
}
});
});
function fetchData(garmentID) {
var url = 'http://staging.me-tail.net/api/3.0/retailer/4/garmentsAvailable?guid=' + applicationID;
$.getJSON(url, function(data) {
var appDetails = data.AvailableSkus[0];
$('#garmentTitle').val(appDetails.AvailableSkus);
});
}
//]]>
</script>
Since data.AvailableSkus seems to be an array, you don't want to pass the collection as the value to #garmentTitle.
You're most likely after a property (if the array contains objects) or the actual element:
//if typeof appDetails.AvailableSkus[0] is string or number:
$('#garmentTitle').val(appDetails.AvailableSkus[0]);
or
//if typeof appDetails.AvailableSkus[0] is an object:
$('#garmentTitle').val(appDetails.AvailableSkus[0].someProp);
value
Type: String or Array
A string of text or an array of strings corresponding to the value of each matched element to set as selected/checked.
This link provides output properly
http://staging.me-tail.net/api/3.0/retailer/4/garmentsAvailable?guid=5
are you sure "applicationID" is setted before ?
var url = 'http://staging.me-tail.net/api/3.0/retailer/4/garmentsAvailable?guid=' + applicationID;
Any error message in firebug console ?

Get json value dynamically

{
"id":["123"],
"optionid_123":"98"
}
I have the id as a variable, but from that how can I get the optionid_*? I tried a few things, but nothing seems to work. The each is inside of the appropriate function and jsonid contains the correct value. Here is my attempt at accessing the value 98 which doesn't work:
$.each(data.id,function(){
var jsonid = this;
console.log( data.optionid_+jsonid ); // doesn't work
});
You can use Bracket notation:
console.log( data['optionid_' + jsonid] );
I think your loop with data.id is not correct. That is
$.each(data.id, function() {..})
is incorrect.
For example if you data looks like following:
var data = [{
"id":["123"],
"optionid_123":"98"
},
{
"id":["456"],
"optionid_456":"99"
}];
Then you need to loop over data and get your required property.
$.each(data, function(index, val) {
var jsonid = val.id[0]; // as val.id is array so you need [0] to get the value
console.log(val['optionid_' + jsonid]); // bracket notation used
});
DEMO

Why do I get an extra element at the end in JSON?

I'm working on some website, and am using JSON. My problem is the JSON.parse method, I use it to send a simple array, and append to an array the values. And I always get an extra element at the end that us just commas. here is the simplified code:
responseText = '["dummy1", "dummy2", "dummy3", "dummy4"]';
var clientList=[];
try {
JSON.parse(responseText, function(key, val){clientList.push(val)});
} catch (e) {
alert('no');
}
alert(clientList.length);
First in IE its not working at all (exception is thrown).
Second chrome the result is that clientList is an array of 5 strings, while the last one is ',,, '.
Why is that extra value there? Can I get rid of it (without just popping the array at the end)? And what is wrong with IE?
This will work:
responseText = '["dummy1", "dummy2", "dummy3", "dummy4"]';
var clientList=[];
try {
clientList = JSON.parse(responseText);
} catch (e) {
alert('no');
}
IE doesn't have JSON as a default in the browser. You need a library like json2.
As for your question, that callback function is really in order to transform your object not build it. For example:
var transformed =
JSON.parse('{"p": 5}', function(k, v) { if (k === "") return v; return v * 2; });
// transformed is { p: 10 }
From parse
There are differences in using JSON under different browsers. One way is to do what IAbstractDownvoteFactory said. Another way is to use jQuery library and
clientList = $.parseJSON(responseText);
should do the job under any browser (although I did not test it under IE).

Categories