I'm looking at a json that looks like this
{
"key": "cow",
"value": "woof"
}
{
"key": "dog",
"value": "moo"
}
And i wan to parse it, but JSON.parse doesn't work because the thing as a whole isn't really json. There actually aren't any newlines either, so it looks like
{"key": "cow","value": "woof"}{"key": "dog","value": "moo"}
As to the why, this is the stream coming from a Comet endpoint. Ideally it should come one by one, but sometimes there's an interruption, and after it comes back i receive the list of all changes that have happened since the interruption happened, strung together. So if three dicts were meant to have come down while the connection was broken, i'll get them all at once at the end:
{"key": "cow","value": "woof"}{"key": "dog","value": "moo"}{"key":"cat","value":"baaa"}
Is there any convenient way of parsing this kind of json in the browser?
EDIT: Sorry guys, i didn't mention that the objects can be arbitrarily nested and can contain all sorts of things, Unicode characters, arrays, objects, arrays with objects, braces of all shapes and sizes, etc. etc. so most hacky string-split or regex solutions will fail in these cases. I didn't put any of these in the examples because i was being lazy, but a more representative example may be
{
"key": "cow",
"value": {
"body": "big",
"name": "sally",
"children": [
"bob",
"daisy"
]
},
"alt-key": "牛"
}
{
"key": "dog",
"value": "moo{}{}{}}}} i love brackets[[[]] ]]]] }{}",
"array": [
"豆沙包",
"叉烧包"
]
}
Although a regex/stringsplit thing would work 95% of the time, I'm looking for a strictly correct solution that'll always work when fed correct json
If values and keys won't contain }{, you could simply add commas to make it valid JSON (and add square brackets to make it an array):
var json = '[' + json.replace(/}{/g, '},{') + ']';
This would even work if you only get a single object as response.
Try like this:
var arrayOfObjects = flowstring.match(/{.*?}/g).map(function(value){
return JSON.parse(value);
});
and you will have this array of objects:
[{"key": "cow","value": "woof"},{"key": "dog","value": "moo"}.......]
If it were me, I'd just write a JSON parser that understands a stream of JSON expressions. JSON is about as easy to parse as grammars get, and making a parser that's able to "reset" itself for a new sentence is a simple (once the parser exists).
Heck you could start from the json.org parser itself.
To reliably "fix" your current data is a project that comes really close to writing a parser anyway.
Try converting that to an array, then parse that. Something like this:
var json = '{"key": "cow","value": "woof"}{"key": "dog","value": "moo"}';
var newjson = '[' + json.replace(/\}\{/g, '},{') + ']';
var obj = JSON.parse(newjson);
Related
I have a weird situation here. I have a text file that is a list of JSON objects and they are separated by line breaks like this:
{"upSpeed": 13.860419184316857, "downSpeed": 85.93058668830014, "time": "2016-12-12T21:31:56.507318"}
{"upSpeed": 13.860419184316857, "downSpeed": 85.93058668830014, "time": "2016-12-12T21:31:56.507318"}
{"upSpeed": 13.890492898595365, "downSpeed": 87.35392034236816, "time": "2016-12-12T21:37:52.174878"}
{"upSpeed": 13.69741910903317, "downSpeed": 88.08812682966898, "time": "2016-12-12T21:41:04.688231"}
...
I use fs.readFile(text file) to load that text file and then array = data.split("\n") to split the text file by line and then insert each line into array, creating a JSON array named array. But, the issue is when I split the original text file using data.split("\n"), the program wraps the resulting object in single quotes (') on either side, resulting in invalid JSON. So, it ends up looking like this:
[ '{"upSpeed": 13.860419184316857, "downSpeed": 85.93058668830014, "time": "2016-12-12T21:31:56.507318"}',
'{"upSpeed": 13.860419184316857, "downSpeed": 85.93058668830014, "time": "2016-12-12T21:31:56.507318"}',
'{"upSpeed": 13.890492898595365, "downSpeed": 87.35392034236816, "time": "2016-12-12T21:37:52.174878"}',
'{"upSpeed": 13.69741910903317, "downSpeed": 88.08812682966898, "time": "2016-12-12T21:41:04.688231"}'
...]
So, is there anyway to avoid the single quotes from being added in so the result is an actual javascript object? I have attempted to create a for loop and loop through each element in the array and run array[i] = array[i].replace(/'/g, ""); to replace the single quotes with nothing ("") but that simply does not work and returns the same exact result shown above. Any ideas?
You don't have "JSON with single quotes". You have a list of JSON strings. The single quotes are just node's way of writing that to the console.
Just parse each of them individually.
var items = data.split(/\n/).map(JSON.parse);
Recommended reading, because I suspect you are mixing up things: Ben Alman's blog - There's no such thing as a "JSON Object".
Have you tried something like : var jsonItem = JSON.parse(array[i]);
I am trying to parse in this result of data which i obtained from xml conversion to json parsing :
var output = [{"SearchResults:searchresults":{"$":{"xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance","xsi:schemaLocation":"someurl","xmlns:SearchResults":"someurl"},"request":[{"keyval":["keydata"]",...}]}]}]}]}]}]}}]
How to get keydata of keyval. I tried parsing and stringify also but no results.
Thanks in Advance
Your unreadable comment does not really shed much light on the issue. My guess is that you retrieve JSON though AJAX with jQuery, thus your JSON is already decoded when you display it in the console (that's what jQuery is good at) and you no longer have a JSON string but good old JavaScript array. Your question is probably the classical "how do I read a deeply nested piece of data" we see a lot here.
Using proper indentation everything's cleaner:
var output = [
{
"SearchResults:searchresults": {
"$": {
"xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance",
"xsi:schemaLocation": "someurl",
"xmlns:SearchResults": "someurl"
},
"request": [
{
"keyval": [
"keydata"
]",
...
First item of array:
output[0]
First key:
output[0]["SearchResults:searchresults"]
Next level:
output[0]["SearchResults:searchresults"]["$"]
... etc.
In JSON, subcategories are sometimes defined using "{" and at other times using "[".
in this example: games -> box -> template , why "[" after games only?
How should the following XML be defined in JSON. How and when should I use "[" and "{"?
<games>
<game id="21934">
<name>Star Wars: The Old Republic</name>
<popularity>30</popularity>
</game>
</games>
Can you give me a good comparison with XML ?
"games": [
{
"name": "Star Wars: The Old Republic",
"popularity": 30,
"id": 21934,
"giantbomb_id": 24205,
"box": {
"template": "http://static-cdn.jtvnw.net/ttv-boxart/Star%20Wars%3A%20The%20Old%20Republic-{width}x{height}.jpg",
"small": "http://static-cdn.jtvnw.net/ttv-boxart/Star%20Wars%3A%20The%20Old%20Republic-52x72.jpg",
"medium": "http://static-cdn.jtvnw.net/ttv-boxart/Star%20Wars%3A%20The%20Old%20Republic-136x190.jpg",
"large": "http://static-cdn.jtvnw.net/ttv-boxart/Star%20Wars%3A%20The%20Old%20Republic-272x380.jpg"
},
You can best answer this question by reading the documentation at json.org.
[ ] are used to define arrays, whereas { } are used to declare objects. Objects are really a form of associative array (mapping name indices to values instead of number
indices to values). In JSON arrays however, the number indices are implicit.
The main advantages of JSON are that it is a subset of Javascript and that it is a compact data interchange format when compared to XML, which is more verbose. JSON data only needs minimal validation whereas XML requires complex parsing. JSON also sacrifices the so called readabilty element of XML, although personally speaking I find it easier to scan JSON to find mistakes than I do wading through XML elements and attributes.
To take your games example, in XML a list of games would be something like this:
<games>
<game id="21934">
<name>Star Wars: The Old Republic</name>
<type>MMORG</type>
</game>
<!-- more game blocks here -->
<game id="12345">...</game>
</games>
In the above example I have skipped niceties such as declaring the fact it is an XML document, linking the above file to a Data Type Definition (DTD) etc.
In JSON the file would probably just be something like this:
{
"games": [
{ "id": 21934, "name" : "Star Wars: The Old Republic", "type": "MMORG" },
{ "id": 12345, .... }
]
}
You could read the above object directly into a Javascript variable and it would be accepted as valid javascript without further processing. It's much faster and easier to get along with. One thing to note is that despite the fact that "games" is an array of objects, it has been encapsulated in {} to be read as a single object.
So in summary, XML is a formal way of exchanging information, whereas JSON sacrifices the formality for ease and speed of use. Be warned however that JSON does have rules and very minor infractions can cause failure to read some or all of the data, depending on browser implementation.
The [] syntax is for arrays where you locate members by number.
The {} syntax is for objects where you locate members by name.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Length of a JavaScript object (that is, associative array)
I have JSON in the following format
[{"student":{"name" : "ABCD",
"age":8,
}
"user":{ "firstName":"ABCD",
"age": 9,
}
},
{"student":{"name" : "XCYS",
"age":10,
}
"user":{ "firstName":"GGG",
"age": 11,
}
},]
I tried using (data.student[i].length), which did not work (just to see what the length of the object is), and I also tried (data.user[i]) to no avail.
I am basically very confused on how I can get the length of one of the objects in the JSON and how I can effectively display it. How can I do this?
The content in your questions doesn't parse as valid JSON as all keys need to be wrapped in quotes (so you should have "age": 11 instead of age: 11). All key/value pairs in an object should be separated by a comma (so you should have "firstName": "GGG", "age": 11 instead of "firstName": "GGG" "age": 11. You also have a trailing comma in the outer array.
So long as you have valid JSON, you should be able to use JSON.parse(data) in all browsers newer than IE7 to convert the string into an actual object. Once parsed into an object, you can use:
var data = "your JSON string";
var object = JSON.parse(data);
console.log(object.length); // the number of objects in the array
console.log(object[0].student.name; // the name of the first student
If you are supporting browsers IE7 and older, check out Douglas Crockford's JSON polyfill: https://github.com/douglascrockford/JSON-js
Please validate your json string in some websites
http://jsonformatter.curiousconcept.com/
Since javascript is a script language, it will interpret the script and terminate the interpretation at the moment when it has some syntax errors. Try to use some javascript console in your browser
IE - Developer Tools
Firefox - firebug plugin
Let's assume that the actual object you have is valid (no missing commas etc), and you've parsed the string correctly, you're trying to access objects with array indexes and vice versa. Let's rebuild the object from ground up:
First, you have an array.
[]
You access the first element in the array using data[0]. The first element is an object.
[
{}
]
The object has two keys, which both hold objects.
[
{
"student": {},
"user": {}
}
]
You access the student key with data[0].student. It contains and object with two keys.
[
{
"student": {
"name": "ABCD",
"age": 8
},
"user": {}
}
]
You get the number of values in that object with:
Object.keys( data[0].student ).length;
For better browser support see Length of a JavaScript object
first, the json is not structured correctly - some element names are missing quotes, commsa in the wrong places, missing, etc. Compare yours to this:
var json = [{"student":{"name" : "ABCD","age":8}, "user":{ "firstName":"ABCD", "age": 9}},
{"student":{"name" : "XCYS","age":10}, "user":{ "firstName":"GGG", "age": 11}}
];
json is easier to proof read that way than spread out vertically. Then, with a simple loop:
for(var ix in json)
{
alert(json[ix].student.name +"="+json[ix].student.age);
}
hopefully you can see how to go from there.
I figured out how to parse it , seems very simple
I used data[i].student.name and data[i].user.name
this seems to alert the correct value
Thank you all for the responses !!
For a web site I'm creating, I have to create a quote based on data provided as a JSON string from the server. I've been looking through this site (and various others) but still am unsure on the best way to query/search the data.
For example, I need to get the Area Name from the Area ID. I need to get the maximum age for an area and also the price for a given minimum/maximum age.
I also want to get an array of prices.
Is it best to create a Javascript object from the string using the eval method? Or should I be using jQuery.
Thanks for your help.
({"SkiPass":[{"Id":1,"Area":"Chamonix","Rates":[{"Id":1,"AgeMin":0,"AgeMax":2,"Price":2.5},{"Id":2,"AgeMin":3,"AgeMax":17,"Price":5.0},{"Id":3,"AgeMin":18,"AgeMax":30,"Price":6.2},{"Id":4,"AgeMin":31,"AgeMax":59,"Price":7.4}]},
{"Id":2,"Area":"Megeve","Rates":[{"Id":1,"AgeMin":0,"AgeMax":2,"Price":1},{"Id":2,"AgeMin":3,"AgeMax":17,"Price":2.0},{"Id":3,"AgeMin":18,"AgeMax":30,"Price":2.2},{"Id":4,"AgeMin":31,"AgeMax":59,"Price":4.4}]},
{"Id":3,"Area":"Verbier","Rates":[{"Id":1,"AgeMin":0,"AgeMax":2,"Price":1.5},{"Id":2,"AgeMin":3,"AgeMax":17,"Price":3.0},{"Id":3,"AgeMin":18,"AgeMax":30,"Price":4.2},{"Id":4,"AgeMin":31,"AgeMax":59,"Price":5.4}]}]})
Create a JavaScript object from the string, most definitely, but do it with legitimate JSON parsing facilities and not "eval()". You could use jQuery, but there are other solutions, such as the JSON tools available from json.org, which are small and simple.
Once it's a JavaScript object, well then your needs should guide you as to whether some query solution is necessary, or instead that it's just a simple matter of programming.
I think the best method is jLinq: http://hugoware.net/Projects/jLinq it's like doing a SQL query on JSON.
It doesn't needs jQuery.
I use it, and it's great.
Create the object from the JSON string using JSON.parse() or jQuery.parseJSON() if you are already using jQuery -- or just pass it as from the server side as JSON.
You can then iterate through the object to find the record you want. Or, you can use build your objects so that you can naturally grab data from them.
FloatLeft - as Dan points out, your task would be much easier if you could use XPath but there is no need to re-write your data in XML format. With DefiantJS (http://defiantjs.com) you can now query JSON structure with XPath expressions.
DefiantJS extends the global object JSON with the method "search", which enables XPath queries and returns an array with the matches (empty array if no matches were found). The returned array is equipped with aggregate functions as well; one of these "sortDesc".
Check out this working fiddle;
http://jsfiddle.net/hbi99/H3PR3/
var data = {
"SkiPass": [
...
{
"Id": 3,
"Area": "Verbier",
"Rates": [
{ "Id": 1, "AgeMin": 0, "AgeMax": 2, "Price": 1.5 },
{ "Id": 2, "AgeMin": 3, "AgeMax": 17, "Price": 3 },
{ "Id": 3, "AgeMin": 18, "AgeMax": 30, "Price": 4.2 },
{ "Id": 4, "AgeMin": 31, "AgeMax": 59, "Price": 5.4 }
]
}
]
},
res1 = JSON.search( data, '//SkiPass[Id=3]/Area' ),
res2 = JSON.search( data, '//*[Area and Id=3]/Rates' )
.sortDesc('AgeMax'); // <-- sorting descending by the value of "AgeMax"
document.getElementById('name').innerHTML = res1;
document.getElementById('max_age').innerHTML = res2[0].AgeMax;
document.getElementById('price').innerHTML = res2[0].Price;