How To Parse A String Of Concatenated JSON In Browser? - javascript

I'm using Socket.IO to move data to the browser. The data sent is a stream of JSON objects, and when it arrives at the browser, it becomes one large string of JSON. The problem is, this JSON can't be parsed by JSON.parse() because it's not "real" JSON.
The data structure can be arbitrary so a RegEx might not do the trick. And this current setup is only temporary. Eventually this stream of JSON will be pre-processed server-side so a stream will not need to be sent to the browser, so I'd like to keep the AJAX/Socket.IO setup I have right now instead of switching over to a JSON stream parser like OboeJS.
What can I do to parse this string of concatenated JSON?
For clarity, the JSON will look like this:
{"a":"A"}{"b":"B"}{"c":"C"}
And I'm trying to parse it in such a way that I can access them like:
console.log(Object.a) //A
console.log(Object.b) //B
console.log(Object.c) //C

In your particular case, you could use Array.prototype.reduce to merge all JSON objects into one:
var unstructuredJson = '{"a":"A"}{"b":"B"}{"c":"C"}';
var jsonArray = "[" + unstructuredJson.split("}{").join("},{") + "]";
var objectArray = JSON.parse(jsonArray);
var result = objectArray.reduce(function(result, item) {
Object.keys(item).forEach(function(propertyName) {
result[propertyName] = item[propertyName];
});
return result;
}, {});
document.body.textContent = JSON.stringify(result);
OP said in some comment:
[...] Each JSON might have nested data like {{}{}}{}{}{}
Then, above approach is broken on this case.
My two cents is that you should put some separator character when you stream these JSON objects and life will be easier: you'll be able to split parent objects easily and you'll just need to change split("}{") with the whole separator.
I suggest you that you use some character that will never happen as part of any property value. You can find a control character on this Wikipedia article: Control character

If each substring is valid JSON but the concatenated part isn't, you can turn the string into a valid array literal and use JSON.parse, then you can process each object using Array methods, e.g. forEach:
var s = '{"a":"A"}{"b":"B"}{"c":"C"}';
var obj = JSON.parse('[' + s.replace(/}{/g,'},{') + ']').forEach(function (obj) {
document.write(JSON.stringify(obj) + '<br>');
});
Or if you want it as a single object:
var s = '{"a":"A"}{"b":"B"}{"c":"C"}';
var obj = JSON.parse(s.replace(/}{/g,','));
document.write(JSON.stringify(obj));

You can use JsonParser to parse concatenated json objects:
ObjectMapper mapper = new ObjectMapper();
JsonFactory factory = new JsonFactory(mapper);
JsonParser parser = factory.createParser(YourJsonString);
List<YourObject> YourObjectList = new ArrayList<>();
Iterator<YourObject> iterator = parser.readValuesAs(YourObject.class);
while(iterator.hasNext()) {
YourObject yourObject = iterator.next();
loginSignalsList.add(yourObject);
}

Split the large string {a:'A'}{b:'B'}{c:'C'} and parse them individually

Related

Remove multiple square brackets using replace() - javascript

I have a response from the server that is like this:
users: ["beautykarttworld","sbdanwar","haiirfavs","show__tanz","kinjal_suhagiya_9999","_adultmafia_"]
It's a string not an array like it appear, since I need an array to work on, how I can remove the square backets and then the commas to obtain a normal array?
I've tried in this way:
var data = ["beautykarttworld","sbdanwar","haiirfavs","show__tanz","kinjal_suhagiya_9999","_adultmafia_"]
data.replace('[', '').replace(']', '').split(',');
but chaining two .replace() functions and a split() isn't the best solution. Can anyone halp me?
In your example data is an array.
However, if data was a string you would convert it to an array like this:
var arr = JSON.parse(data);
In short,
Here you have provided data in normal string formate not in JSON string formate
var data = 'users: ["beautykarttworld","sbdanwar","haiirfavs","show__tanz","kinjal_suhagiya_9999","_adultmafia_"]'
var squareBracketData = data.substr(data.indexOf("["))
var array = JSON.parse(squareBracketData)
console.log(array)
Some personal advice, Try to send JSON stringify data from the
server so it will make your life easy
Example:
var users =["beautykarttworld","sbdanwar","haiirfavs","show__tanz","kinjal_suhagiya_9999","_adultmafia_"]
// Stringify data
var data = JSON.stringify({users})
console.log("Data")
console.log(data)
// retrieve data from string
var parsedData = JSON.parse(data)
var parsedUsers = parsedData.users
console.log("parsedUsers")
console.log(parsedUsers)

Construct nested escaped JSON string for JSON.parse() recursive retreival

The server returns me a JSON string like this:
{"payload":{"data":"{\"notification_type\":\"{\"type1\":\"{\"type2\":\"type2 value\"}\"}\"}"}}
This string, as I understand, cannot be parsed with JSON.parse() API because the nested JSON strings within the string should be properly escaped. If the string is not properly escaped I get the below error:
Uncaught SyntaxError: Unexpected token n in JSON at position 22
So, the string should be properly escaped respecting the nested nature like below so that JSON.parse() can process it:
var properString = "{\"payload\":{\"data\":\"{\\\"notification_type\\\":\\\"{\\\\\\\"InternalKey\\\\\\\":\\\\\\\"InternalValue\\\\\\\"}\\\"}\"}}";
console.log("Proper String = ");
console.log(properString);
var firstLevelObject = JSON.parse(properString);
console.log("First Level Object = ");
console.log(firstLevelObject);
var secondLevelObject = JSON.parse (firstLevelObject.payload.data);
console.log("Second Level Object = ");
console.log(secondLevelObject);
var thirdLevelObject = JSON.parse(secondLevelObject.notification_type);
console.log("Third Level Object = ");
console.log(thirdLevelObject);
This is how google chrome's console outputs the same:
I however am unable to convert the improper string from server to properly escaped string as defined in the variable properString so that the JSON is properly constructed which can be traversable. How can the string be converted with proper escape characters?
Reference sources:
I have referred to this answer to understand how nested escape characters should be added, but the answer does not state how conversion can be done.
Actually, the JSON string what you get is not exactly right. It's not a right JSON syntax in the nested JSON String. But you can rebuilt it to a correct JSON syntax string via regular expression or native JS.
var obj = '{"payload":{"data":"{\"notification_type\":\"{\"type1\":\"{\"type2\":\"type2 value\"}\"}\"}"}}';
var payloadString = obj.substring(0, 20).concat('"}}');
obj = obj.substring(20, obj.length - 3).replace("\"{", "{").replace("}\"}", "}}").replace("}\"}", "}}").replace("\"{", "{");
var data = JSON.parse(obj);
var obj2 = JSON.parse(payloadString);
//console.log(payload);
//console.log(data);
obj2.payload.data = data;
console.log(obj2);

Node-Red Having Issues Parsing Payload Data

I have node red successfully running and am feeding it from a couple of different PLC systems,
I have a payload like this.
{"d":779,"dt":3,"ts":"2018-04-05T19:54:12.930758Z","q":18}
The fields would break down to.
d=779 dt=3 ts=2018-04-05T19:54:12.930758Z q=18
I have been attempting to parse the string and break it down (even just one field "d").
I have been trying to write a function to parse the data using combinations of splice and split.
Does anyone have a simple solution to this? Am I even using the correct node process?
I know this is completely not working but it was an attempt the read the first field. It is not padded and therefore needs to start where the colon is and end with the comma.
var str = msg.payload;
var th = str.slice(5,-1);
th = th.split(",");
msg.payload[0] = parseFloat(th[0]);
return [ msg.payload[0]];
Have a source MQTT Buffer of:
[123,34,100,34,58,51,48,54,56,44,34,100,116,34,58,50,44,34,116,115,34,58,34,50,48,49,56,45,48,52,45,49,50,84,48,56,58,53,48,58,49,56,46,49,54,50,48,48,48,90,34,44,34,113,34,58,49,57,50,125,0]
The Zero at the end is obviously the offending value:
I am attempting to remove it with function
var data = msg.payload;
console.log("payload data: length = " + data.length);
data = data.trim();
console.log("trimmed data: length = " + data.length);
msg.payload = JSON.parse(data);
return msg;
Now am getting TypeError: data.trim is not a function
Flow looks like:
enter image description here
Now getting
Thanks,
Kevin
By default most nodes will be outputing a JSON object already so there will be no need to parse it as a string just access the objects values directly e.g.
var d = msg.payload.d;
If the nodes are output String representations of JSON then you should use the built in JSON node to convert the string in msg.payload to a JSON object before accessing the values.
Also you need to return a whole JSON object from a function node, not just a string (or an array of strings)
So if you just want to the pass the d value on it should be:
var d = msg.payload.d;
msg.payload = d;
return d;

Javascript: How to convert JSON dot string into object reference

I have a string: items[0].name that I want to apply to a JSON object: {"items":[{"name":"test"}]} which is contained in the variable test. I want to apply that string to the object in order to search it (test.items[0].name). I can only think of one way to do this: parse the square brackets and dots using my own function. Is there another way I can do this? Perhaps using eval? (Even though I'd LOVE to avoid that...)
For clarity:
I have a JSON object, what is inside of it is really irrelevant. I need to be able to query the object like so: theobject.items[0], this is normal behaviour of a JSON object obviously. The issue is, that query string (ie. items[0]) is unknown - call it user input if you like - it is literally a string (var thisIsAString = "items[0]"). So, I need a way to append that query string to theobject in order for it to return the value at theobject.items[0]
function locate(obj, path) {
path = path.split('.');
var arrayPattern = /(.+)\[(\d+)\]/;
for (var i = 0; i < path.length; i++) {
var match = arrayPattern.exec(path[i]);
if (match) {
obj = obj[match[1]][parseInt(match[2])];
} else {
obj = obj[path[i]];
}
}
return obj;
}
var name = locate(test, 'items[0].name');
...JSON doesn't have objects, it's just a string.
If you're dealing with an object (ie: you can reference it using dot/bracket notation) then it's just a JavaScript object/array...
So depending on what the deal is, if you're dealing with a 100% string:
'{"name":"string","array":[0,1,2]}'
Then you need to send it through JSON.parse;
var json_string = '{"name":"string","array":[0,1,2]}',
js_obj = JSON.parse(json_string);
js_obj.name; // "string"
js_obj.array; // [0,1,2]
js_obj.array[1]; // 1
If it's not a string, and is indeed an object/array, with other objects/arrays inside, then you just need to go:
myObj.items[0].name = items[0].name;
If it IS a string, then .parse it, and use the parsed object to do exactly what I just did.
If it needs to be a string again, to send to the server, then use JSON.stringify like:
var json_string = JSON.stringify(js_obj);
Now you've got your modified JSON string back.
If you need to support GhettoIE (IE < 8), then download json2.js from Douglas Crockford, and add that script on the page conditionally, if you can't find window.JSON.

Best way to convert string to array of object in javascript?

I want to convert below string to an array in javascript.
{a:12, b:c, foo:bar}
How do I convert this string into array of objects? Any cool idea?
I think that the best way of doing this, as Douglas Crockford (one of the biggests gurus of JavaScript) suggests in here is using the JSON native parser, as it is not only faster than the eval(), it's also more secure.
Native JSON parser is already available in:
Firefox 3.5+
IE 8+
Opera 10.5+
Safari Safari 4.0.3+
Chrome (don't know which version)
And Crockford has made a safe fallback in javascript, called json2.js, which is an adaption of the eval() approach, with some security bits added and with the native JSON parsers API. You just need to include that file, remove its first line, and use the native JSON parser, and if it's not present json2 would do the work.
Here is an example:
var myJSONString = '{ "a": 1, "b": 2 }',
myObject = JSON.parse(myJSONString);
Once parsed you'll get an object with attributes a and b, and as you may know, you can treat an object as a hash table or associative array in JavaScript, so you would be able to access the values like this:
myObject['a'];
If you just want a simple array and not an associative one you could do something like:
var myArray = [];
for(var i in myObject) {
myArray.push(myObject[i]);
}
Lastly, although not necessary in plain JavaScript, the JSON spec requires double quoting the key of the members. So the navite parser won't work without it. If I were you I would add it, but if it is not possible use the var myObject = eval( "(" + myString + ")" ); approach.
Since your string is malformed JSON, a JSON parser can't parse it properly and even eval() will throw an error. It's also not an Array but a HashMap or simply an Object literal (malformed). If the Object literal will only contain number and string values (and no child objects/arrays) you can use the following code.
function malformedJSON2Array (tar) {
var arr = [];
tar = tar.replace(/^\{|\}$/g,'').split(',');
for(var i=0,cur,pair;cur=tar[i];i++){
arr[i] = {};
pair = cur.split(':');
arr[i][pair[0]] = /^\d*$/.test(pair[1]) ? +pair[1] : pair[1];
}
return arr;
}
malformedJSON2Array("{a:12, b:c, foo:bar}");
// result -> [{a:12},{b:'c'},{foo:'bar'}]
That code will turn your string into an Array of Objects (plural).
If however you actually wanted a HashMap (Associative Array) and NOT an array, use the following code:
function malformedJSON2Object(tar) {
var obj = {};
tar = tar.replace(/^\{|\}$/g,'').split(',');
for(var i=0,cur,pair;cur=tar[i];i++){
pair = cur.split(':');
obj[pair[0]] = /^\d*$/.test(pair[1]) ? +pair[1] : pair[1];
}
return obj;
}
malformedJSON2Object("{a:12, b:c, foo:bar}");
// result -> {a:12,b:'c',foo:'bar'}
The above code will become a lot more complex when you start nesting objects and arrays. Basically you'd have to rewrite JSON.js and JSON2.js to support malformed JSON.
Also consider the following option, which is still bad I admit, but marginally better then sticking JSON inside an HTML tag's attribute.
<div id="DATA001">bla</div>
<!-- namespacing your data is even better! -->
<script>var DATA001 = {a:12,b:"c",foo:"bar"};</script>
I am assuming you omit quote marks in the string because you had put it inside an HTML tag's attribute and didn't want to escape quotes.
The simplest, but unsafe way to do it is:
eval('(' + myJSONtext + ')')
But since this will interpret any javascript code, it has security holes. To protect against this use a json parser. If you're using a framework (jquery, mootools, etc.) there's a framework-specific call. Most of them are based on Douglas Crawford's parser available at http://www.json.org/js.html.
You can use "for in"
var myObject = {a:'12', b:'c', foo:'bar'};
var myArray = [];
for(key in myObject) {
var value = myObject[key];
myArray[key] = value;
}
myArray['a']; // returns 12
Notes: considering that myObject only have one level of key-value pairs.
JSON.parse will do the trick. Once parsed, you can push them into the array.
var object = JSON.parse(param);
var array = [];
for(var i in object) {
array.push(object[i]);
}
If you're using jQuery, there's the $.parseJSON() function. It throws an exception if the string is malformed, and "Additionally if you pass in nothing, an empty string, null, or undefined, 'null' will be returned from parseJSON. Where the browser provides a native implementation of JSON.parse, jQuery uses it to parse the string"
Use safe evaluation. Unlike JSON.parse, this doesn't require the keys or values to be quoted. Quote values only if they contain embedded commas.
const myStr = "{a:1, b:2, c:3}";
const myObj = string_exp(myStr);
console.log("dot: " + myObj.c);
function string_exp(sCmd) {
return Function(`'use strict'; return (${sCmd})`)();
}
https://dev.to/spukas/everything-wrong-with-javascript-eval-35on#:~:text=the%20variable%20exists.-,Alternatives,-The%20most%20simple

Categories

Resources