How to parse JSON that has inner layers using Javascript? - javascript

I can eval simple JSON with javascript.
var json = '{"amount":"50","id":"3"}';
var out = eval("{" + json + "}");
Now I am using JPA with REST and JSON-nized query result would include table name which makes
JSON having inner JSON so simple eval wouldn't work.
{"inventory":{"amount":"50","id":"3"}}
I've looked around the web for solution but can't find my case.
Should I just do string manipulation and extract {"amount":"50","id":"3"} part?
Or is there other way?

Yes, there is another (better) way! Use JSON.parse() to parse your JSON and get your object out:
var obj = JSON.parse(jsonString);
//then, for example...
var amount = obj.inventory.amount;
For older browsers (IE <8 for example) without native JSON support, include json2.js so this above still works.

Even this should work:
var json = '{"inventory":{"amount":"50","id":"3"}}';
var out = eval("{" + json + "}");
alert(out.inventory.amount);
But better to use JSON.parse

Aniway, I think that the proper way to perform a simple eval is to have the json string surrounded with parenthesis, not curly brackets...
var out = eval("(" + json + ")");
Cf. https://github.com/douglascrockford/JSON-js/blob/master/json.js :
// In the third stage we use the eval function to compile the text into a
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
// in JavaScript: it can begin a block or an object literal. We wrap the text
// in parens to eliminate the ambiguity.
j = eval('(' + text + ')');

Related

javascript .replace() does not replace every occurence

I get the following when retrieving it.
var data = {"distinct_id"%3A "2222222222222"%2C"%24initial_referrer"%3A "%24direct"%2C"%24initial_referring_domain"%3A "%24direct"}
If I check for typeof data I get a String back.
However, when I try to make a proper object out of it by replacing "%3A" with ":" etc the above object does not replace all occurrences but only the first.
data = data.replace(/\%3A/g,":") only replaces the first "%3A".
How can I make a proper object out of this with distinct_id, $initial_referrer as well as we $initial_referring_domain ?
Testing your code proves that your replace usage is actually okay, it indeed replaces all occurrences of %3A:
var data = '{"distinct_id"%3A "2222222222222"%2C"%24initial_referrer"%3A "%24direct"%2C"%24initial_referring_domain"%3A "%24direct"}';
data = data.replace(/\%3A/g, ":");
alert(data);
However, regular expressions is not correct approach here, as you also have other encoded entities. Use decodeURIComponent function instead:
var data = '{"distinct_id"%3A "2222222222222"%2C"%24initial_referrer"%3A "%24direct"%2C"%24initial_referring_domain"%3A "%24direct"}';
data = decodeURIComponent(data);
alert(data);

ES6 when to use String.raw over default template literal

I'm trying to concatenate a bunch of strings to build a query string in Javascript. Previously I have achieved this through ugly string concatenation:
var queryString = "?action=" + actionValue + "&data=" + dataValue";
But with ES6 I see that there are new methods provided that could help me achieve the same result with much nicer looking code, like string interpolation in C# 6:
string s = $"action={actionValue}&data={dataValue}"
I have tested with both default template literal and String.raw and although the syntax for each is slightly different, they both work. I'm leaning towards using String.raw in my final copy as it doesn't allow for the string to be tagged and thus tinkered with in the future like the default template literal does.
Although it does say in the MDN docs that String.raw basically calls the default template literal method but I like the syntax of String.raw better... I am calling the String.join method inside the curly braces of my string that I am formatting so maybe that is a misuse of String.raw.
Are any ES6 wizards out there able to enlighten me and provide reasons for one over the other?
My code:
var defaultTemplateStringUrl = `#Url.Action("DownloadMultiple")?inIds=${inData.join(',')}&outIds=${outData.join(',')}&truckId=${truckId}`;
var rawStringUrl = String.raw `#Url.Action("DownloadMultiple")?inIds=${inData.join(',')}&outIds=${outData.join(',')}&truckId=${truckId}`;
window.open( /*url goes here*/);
A template literal produces a string. If you use String.raw, you will get the raw form of that string:
`a\tb`; // "a b"
String.raw`a\tb`; // "a\tb"
So you should use String.raw only when you want the raw form.
No, using String.raw makes no sense for you.
You should rather write your own template tag that does the necessary URL encoding and handles arrays in a manner you like.
function myUrl(parts) {
var url = parts[0];
for (var i=1; i<arguments.length; i++) {
var val = arguments[i];
if (Array.isArray(val))
val = val.join(",");
url += encodeURIComponent(val);
url += parts[i];
}
return url;
}
Then you can use
window.open(myUrl`#Url.Action("DownloadMultiple")?inIds=${inData}&outIds=${outData}&truckId=${truckId}`);

JSON.Parse,'Uncaught SyntaxError: Unexpected token o [duplicate]

This question already has answers here:
I keep getting "Uncaught SyntaxError: Unexpected token o"
(9 answers)
Closed 6 years ago.
I am having trouble with JSON returned from a web service. It looks like the JSON lacks quotes, but when I add quotes to the JSON, I get an error. Here is the error message: 'Uncaught SyntaxError: Unexpected token o. When I log the string to console:[object Object],[object Object]
Here is some example code that simulates the error:
//Error I am trying to solve
var jsonString = '[{"Id":"10","Name":"Matt"},{"Id":"1","Name":"Rock"}]';
var myData = JSON.parse(jsonString);
$(document).ready(function() {
var $grouplist = $('#groups');
$.each(myData, function() {
$('<li>' + this.Name + '</li>').appendTo($grouplist);
});
});
Here is the same code with the single quotes around the string. It works
//Successful Javascript
var jsonString = '[{"Id":"10","Name":"Matt"},{"Id":"1","Name":"Rock"}]';
var myData = JSON.parse(jsonString);
$(document).ready(function() {
var $grouplist = $('#groups');
$.each(myData, function() {
$('<li>' + this.Name + '</li>').appendTo($grouplist);
});
});
//Successful HTML
<ul id="groups"></ul>
But when I try to add quotes to the string, like I seem to need to in my real code, it fails:
//Does not work when I need to append quotes to the string:
var jsonStringNoQuotes = [{"Id":"10","Name":"Matt"},{"Id":"1","Name":"Rock"}];
jsonStringQuotes = "'" + jsonStringNoQuotes + "'";
var myData = JSON.parse(jsonStringQuotes);
$(document).ready(function() {
var $grouplist = $('#groups');
$.each(myData, function() {
$('<li>' + this.Name + ',' + this.Id + '</li>').appendTo($grouplist);
});
});
Here is the error:
log string to console:[object Object],[object Object]
data.js:809 Uncaught SyntaxError: Unexpected token '
I'm stumped. Any help appreciated! Thank you!
Without single quotes around it, you are creating an array with two objects inside of it. This is JavaScript's own syntax. When you add the quotes, that object (array+2 objects) is now a string. You can use JSON.parse to convert a string into a JavaScript object. You cannot use JSON.parse to convert a JavaScript object into a JavaScript object.
//String - you can use JSON.parse on it
var jsonStringNoQuotes = '[{"Id":"10","Name":"Matt"},{"Id":"1","Name":"Rock"}]';
//Already a javascript object - you cannot use JSON.parse on it
var jsonStringNoQuotes = [{"Id":"10","Name":"Matt"},{"Id":"1","Name":"Rock"}];
Furthermore, your last example fails because you are adding literal single quote characters to the JSON string. This is illegal. JSON specification states that only double quotes are allowed. If you were to console.log the following...
console.log("'"+[{"Id":"10","Name":"Matt"},{"Id":"1","Name":"Rock"}]+"'");
//Logs:
'[object Object],[object Object]'
You would see that it returns the string representation of the array, which gets converted to a comma separated list, and each list item would be the string representation of an object, which is [object Object]. Remember, associative arrays in javascript are simply objects with each key/value pair being a property/value.
Why does this happen? Because you are starting with a string "'", then you are trying to append the array to it, which requests the string representation of it, then you are appending another string "'".
Please do not confuse JSON with Javascript, as they are entirely different things. JSON is a data format that is humanly readable, and was intended to match the syntax used when creating javascript objects. JSON is a string. Javascript objects are not, and therefor when declared in code are not surrounded in quotes.
See this fiddle:
http://jsfiddle.net/NrnK5/
var jsonStringNoQuotes = [{"Id":"10","Name":"Matt"},{"Id":"1","Name":"Rock"}];
it will create json object. no need to parse.
jsonStringQuotes = "'" + jsonStringNoQuotes + "'";
will return '[object]'
thats why it(below) is causing error
var myData = JSON.parse(jsonStringQuotes);
Your last example is invalid JSON. Single quotes are not allowed in JSON except inside strings. In the second example, the single quotes are not in the string, but serve to show the start and end.
See http://www.json.org/ for the specifications.
Should add: Why do you think this: "like I seem to need to in my real code"? Then maybe we can help you come up with the solution.
Maybe what comes from the server is already evaluated as JSON object? For example, using jQuery get method:
$.get('/service', function(data) {
var obj = data;
/*
"obj" is evaluated at this point if server responded
with "application/json" or similar.
*/
for (var i = 0; i < obj.length; i++) {
console.log(obj[i].Name);
}
});
Alternatively, if you need to turn JSON object into JSON string literal, you can use JSON.stringify:
var json = [{"Id":"10","Name":"Matt"},{"Id":"1","Name":"Rock"}];
var jsonString = JSON.stringify(json);
But in this case I don't understand why you can't just take the json variable and refer to it instead of stringifying and parsing.

Javascript replace for equal symbol

I am getting my response as following
var val = {"Type"=>"D","Number"=>33"}
From above i try to change like this
var MyArray = {"Type": "D", "Number": "33"};
for(key in MyArray)
{
alert("key " + key
+ " has value "
+ MyArray[key]);
}
I tried replace, replace all but those not working. Any suggestions?
Server side code pasted from comments...
new_transfer_header = #params['my_extra_param']
p new_transfer_header,'------------ ew_transfer_header----------,new_transfer_header.class
WebView.execute_js("replaceDeliveryWithScanUnit('#{new_transfer_header}')")
puts result as "{\"Type\"=>\"D\", \"Number\"=>\"33\"}
var val = {"Type"=>"D","Number"=>33"}
Is invalid JavaScript - there is no way to fix it within the same script/script block since it fails parsing.
Likely you need to eliminate extra HTML encoding that somone done for this chunk of script on the server.
If it is text received by some AJAX call you should be able to replace " and similar values with corresponding characters and than parse with JSON.parse.
you could use string.replace and cal eval on the result I think, but would it be better to get valid json from the server ?

How do I convert a JSON string to a function in javascript?

How can I convert a string in javascript/jquery to a function?
I am trying to use a JSON parameter list to initialize a function. However, one of the parameters is a function, which I store as a string, and I get an error when I try to use eval() to return the function.
For example, if my JSON is:
json = { "one": 700, "two": "function(e){alert(e);}" }
Then in my code:
parameters = eval(json);
$('myDiv').addThisFeature({
parameter_1: json.one,
parameter_2: eval(json.two) // <= generates error
})
Example: http://jsfiddle.net/patrick_dw/vs83H/
var json = '{ "one": 700, "two": "function(e){alert(e);}" }';
var parameters = JSON.parse( json );
eval( 'var func = ' + parameters.two );
func( 'test' ); // alerts "test"
You'll need to load the JSON library in browsers that don't support it.
Or do two separate evals:
Example: http://jsfiddle.net/patrick_dw/vs83H/1/
var json = '{ "one": 700, "two": "function(e){alert(e);}" }';
eval( 'var parameters = ' + json );
eval( 'var func = ' + parameters.two );
func( 'test' );
I assume you're aware of the dangers of eval.
Looking for a way to not use eval this is the best I could come up with. Use the Function constructor to create a function from a string.
var parsed = JSON.parse('{"one":"700", "two":"function(){return 0;}" }');
var func = new Function('return ' + parsed.two)(); // return parsed.two function
alert(typeof func); // function
alert(func()) // 0
Use this:
parameters = eval('(' + json + ')');
$('#myDiv').addThisFeature({
parameter_1: parameters.one,
parameter_2: eval('(' + parameters.two + ')') // <= does not generate an error
});
Adding the parentheses at the beginning and end of the string prevents the syntax error.
Note, however, that you are parsing JSON using eval (which in some cases has security risks, but I assume that is irrelevant because you do want to run arbitrary code sent by the server). If you have the server-side flexibility (to send invalid JSON), you could just send the function not quoted as a string and eval should be able to parse that just fine.
See this SO question. As was said, JSON is meant to hold data. To treat a piece of the data as a function, you would first need to eval the string.
You are eval'ing an anonymous function, which of course won't be called by anything. If you really wanted to run the code in the json then the text would need to be alert(e).
However it doesn't sound like a very sensible thing to do. You'd be better off writing code to deal with the contents of the json object, rather than trying to run code embedded in the json.
Neither way is particularly nice, but if you can get rid of the function(e) wrapper bits, then you can use var myDynamicFunction = new Function("e", "alert(e);"); Otherwise, you're looking at using eval(). Eval() is evil in general. If this is JSON that you're getting back from a $.getJSON call or something, you're opening yourself up to security concerns.

Categories

Resources