Can't manipulate JSON object in any way - javascript

I'm making a website on Cargocollective and customizing parts of it with Javascript (only vanilla allowed). I figured out Cargo stores the whole website in the same HTML using JSON notation, in <script type="text/json"> elements.
I want to extract information from those JSON objects to use in my script. I am able to select the JSON object using queryselectors. The objects looks like a JSON object, and typeof returns object.
However, if I try to do something like myObject.key, or myObject[0].key, I get "undefined". If I try to JSON.parse I get "Unexpected token o in JSON at position 1". JSON.stringify returns {}.
This is what it looks like in the HTML: (it's very long, 4000 characters, this is just an excerpt)
<script type="text/json" data-set="ScaffoldingData" >{"id":0,"title":"Sandra Javera","project_url":0,"set_id":0,"is_homepage":false,"pin":false,"is_set":true,"in_nav":false,.........},{"id":14844451,"site_id":711279,"project_url":"Lisboa-copy","direct_link":"https:\/\/sandrajavera.com\/Lisboa-copy","type":"page","title":"Lisboa copy","title_no_html":"Lisboa copy","tags":"","display":true,"pin":false,"pin_options":null,"in_nav":false,"is_homepage":false,"backdrop_enabled":false,"is_set":false,"stack":false,"excerpt":"+\n\t\t\n..........}\"</script>
So the JSON object has a structure like
{
"key": value,
"key": value,
"key": value
},
{
"key": value,
"key": value,
"key": value
},
{
"key": value,
"key": value,
"key": value
}
so it's actually an array of objects even though there are no brackets.
The website is sandrajavera.com. Any help is appreciated. Thank you.

Wrap the text in [] to make the structure valid and then parse it.
Adding the wrapping array braces would be better done at the source however
const str = document.querySelector('script[data-set]').textContent.trim()
const data = JSON.parse(`[${str}]`)
console.log(data)
<script type="text/json" data-set="ScaffoldingData" >
{ "id": 1,"txt": "foo"}, { "id": 2, "txt": "bar" }
</script>

Related

How to pull out JSON data using the keyname and indexing across entire array, across multiple unnamed objects [duplicate]

This question already has answers here:
From an array of objects, extract value of a property as array
(24 answers)
JavaScript property access: dot notation vs. brackets?
(17 answers)
Closed 5 months ago.
I am tying to pull some data points out of JSON data to create an array or list of data using JSON.parse. Below is the example data. I want to end up with something that returns [5490, 5510, 5520, 5530, 5540] Is it possible to do this using indexing instead of iterating through the array and appending to a new list? A loop would work fine but I'm wondering if this can be done in one clean line of code using brackets. EDIT: What I really want is a solution that involves indexing using brackets. This question was closed and marked as answered in this thread, however none of those answers provide a one-line solution using indexing. Is this not possible? If that's the case, that would be a satisfactory answer to this question.
This is what I have tried:
const JSON1 = JSON.parse(JSON.stringify(data))
JSON.stringify(JSON1.value.timeSeries[0].values[0].value[0].values
this returns only 5490, which does make sense because I am telling it to grab only the first object in that "value" array. In python I believe you could do something like JSON1.value.timeSeries[0].values[0].value[:].values replacing the last index with : to denote all objects and then grab the final value: from each object to return [5490, 5510, 5520, 5530, 5540] but JS doesn't seem to have an equivalent syntax to yield that result.
Another thing I tried was JSON.stringify(JSON1.value.timeSeries[0].values[0].value.values with no index on "value" but this doesn't work due to the brackets in the JSON data, it returns nothing. I could write a function to remove the brackets from the string and it would work, but that also seems like a poor option unless what I am asking for is impossible.
Any help is greatly appreciated. If you made it this far, thank you for your time.
example JSON:
"value": {
"timeSeries": [
"values": [
{
"value": [
{
"value": "5490",
"qualifiers": [
"P"
],
"dateTime": "2022-09-18T23:45:00.000-04:00"
},
{
"value": "5510",
"qualifiers": [
"P"
],
"dateTime": "2022-09-19T00:00:00.000-04:00"
},
{
"value": "5520",
"qualifiers": [
"P"
],
"dateTime": "2022-09-19T00:15:00.000-04:00"
},
{
"value": "5530",
"qualifiers": [
"P"
],
"dateTime": "2022-09-19T00:30:00.000-04:00"
},
{
"value": "5540",
"qualifiers": [
"P"
],
"dateTime": "2022-09-19T00:45:00.000-04:00"
}]}]]}

Get json data structure with nodejs

This is a problem that is so hard for me to find using just keywords -- I've scrolled pages after pages and all the hits are on getting data from json structure, instead of getting data structure from json.
If you don't know what goal I'm trying to achieve, here are tools to get data structure from json to Go:
https://mholt.github.io/json-to-go/
This tool instantly converts JSON into a Go type definition
https://json2struct.mervine.net/
Convert JSON in to a useful struct.
https://transform.tools/json-to-go
online playground to convert JSON to Go Struct
For one specific application, I'm getting data with all kinds of slightly different json data structures, which makes my data extraction failing all the times. I need to compare those data structure-wise, as each individual json data are surely different.
It looks like you're struggling to find what you want because vanilla JavaScript doesn't have the type concepts you're trying to use.
You probably want to generate a json schema or a typescript interface, and searching "JSON to schema npm" will get you more useful results.
One such example is to-json-schema
import toJsonSchema from 'to-json-schema';
toJsonSchema({ "foo": "bar", "x": [1, 2] });
/* returns
{
"type": "object",
"properties": {
"foo": {
"type": "string"
},
"x": {
"type": "array",
"items": {
"type": "integer"
}
}
}
}
*/
For more specific answers you'd need to provide some minimal sample of input and output, e.g. what would you expect from { "foo": "bar", "x": [1, 2] }

Best way to JSON parsing using JavaScript [duplicate]

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 !!

Parsing stuck-together json in javascript

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);

Querying/Searching for Values within JSON

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;

Categories