Hi I am trying to parse the following bit of json with Jquery so far I can get everything out of the results that I want apart from one crucial piece of information the performance tags.
Each json result is wrapped in an event tag and then within this there is info like time and date etc formatted in the following way
"location": {
"lng": -0.1187418,
"city": "London, UK",
"lat": 51.4681089
},
"start": {
"time": "19:30:00",
"datetime":"2010-02-16T19:30:00+0000",
"date": "2010-02-16"
},
I have managed to loop through this and parse it to html. However there is one set of tags for 'performance' that are formatted differently.
"performance": [{
{
"artist": {
"uri": "http://www.songkick.com/artists/288696-vampire-weekend",
"displayName": "Vampire Weekend",
"id": 288696,
"identifier": [{"mbid": "af37c51c-0790-4a29-b995-456f98a6b8c9"}]
}
"displayName": "Vampire Weekend",
"billingIndex": 1,
"id": 5380281,
"billing": "headline"
}
}],
now in my for loop i am running the following code which displays the performance information in the console.
var events = data.resultsPage.results.event;
for (var i = 0, l = events.length; i < l; i++) {
console.log(events[i].performance); }
However when i try to go into the structure like i have been with the other elements I get returned undefined i.e
console.log(events[i].performance.displayName);
Do I have to do this in a different way because of the use of the [ ] brackets in the performance tag in the Json?
Thanks in advance
Assuming that what you posted is not exactly what your JSON looks like (because what's posted has a syntax error), the "performance" attribute is an array of objects. To get at the "displayName", therefore, you'd need to know which element of the "performance" array you wanted. You'd then access it by index.
console.log(events[i].performance[j].displayName);
(assuming you looped through the "performance" array with the variable "j".)
Try to validate your returned JSON object here, I guess there is some issue with the JSON output..
Related
I am encountering a weird problem with what I believe to be the way Javascript references variables. The project I am working in is Typescript, but this functionality is from vanilla Javascript.
I have an object all_obj set further up in the code.
The following code:
all = [];
data = [];
console.log(all_obj);
Outputs:
{
"1593561600000": {
"date": 1593561600000,
"volume": 24463,
"value": 165049285,
"rank": 0
},
"1596240000000": {
"date": 1596240000000,
"volume": 24366,
"value": 158841976,
"rank": 0
},
"1604188800000": {
"date": 1604188800000,
"volume": 30034,
"value": 196655815,
"rank": 0
},
This goes on 9 more times with similar objects
}
This, works as expected.
However the following code somehow logs something completely different:
let all = [];
let data = [];
console.log(all_obj);
for (let key of Object.keys(all_obj)) {
all.push(all_obj[key]);
}
this.data.push(
{
brand: 'all_aggregated',
datapoints: [...all],
},
{
brand: 'all_mean',
datapoints: [...all].map((dp: brand_datapoint) => {
dp.value = +(dp.value / dp.volume).toFixed(2);
return dp;
}),
}
);
It logs this:
{
"1593561600000": {
"date": 1593561600000,
"volume": 24463,
"value": 6746.89,
"rank": 0
},
"1596240000000": {
"date": 1596240000000,
"volume": 24366,
"value": 6519,
"rank": 0
},
"1604188800000": {
"date": 1604188800000,
"volume": 30034,
"value": 6547.77,
"rank": 0
},
9 more like this
}
As you can see, in the second example. The "value"'s within the all_obj's children is now in the thousands, instead of the hundreds of millions. Also, it is formatted to 2 decimal places. This is suspiciously the formatting I am doing in this line towards the end of the second code example:
dp.value = +(dp.value / dp.volume).toFixed(2);
How on earth is changing the values propagating back up the code???
Especially through [...all]
This is running in an Angular Project. I have trimmed off the bloat, if you need more info of course ask for it, but I didn't want to paste 300 lines of code in here :)
I have been fighting with this for about 6 hours now, and have completely rewritten the same code in about 15 different ways. So I am completely baffled what is causing this.
Solution!
The issue isn't that the data is propagating back up to all_obj, it's that values were being set in the pink arrow, and were being picked up in the red arrow because they were just referencing to it. I thought [...all] would fix it but that just builds a new array with the same references.
The problem is that you are editing the value on the same object that you started with.
When you do all.push(all_obj[key]);, you are filling all with a bunch of references to the inner objects in all_obj. Since these are simply references, interacting with them changes the same objects as the the ones in all_obj. So when you set the value dp.value =, it is "propagating back up the code" because it is the same object that is inside all_obj.
Since you want to make these changes on a new object for just formatting reasons, you should make a copy of the object and only edit the values there. Since the datapoints seem to be simple, with only simple numbers as properties, you can easily make a copy with
dp = {...dp};
You should do this before you change the value.
You may be thinking that this shouldn't be needed, because of the [...all]. However, that will only make a copy of the all list itself, not of all the content. So basically it is a "new list" that contains all the same references to all the same objects.
You may be interested in Is JavaScript a pass-by-reference or pass-by-value language?
EDIT:
Taking another look, it would probably be better/cleaner to make the copy right as you are building the all array. So instead of doing
all.push(all_obj[key]);
You can do
all.push({...all_obj[key]});
Then you don't need to worry about changing the original data as you manipulate the points for formatting or display.
I am currently using Angular to read in a json file and output it onto a table.
Because some of the objects are a little different, I want to make a check to see if job.text exists.
[
{
"job": {
"href": "www.google.com",
"text": "Google"
},
"api": "Some Text Here"
},
{
"job": "Yahoo",
"api": "More text here"
}
]
If job.text exists, then display job.text
else display job
Here is my html from angular but only displaying objects with job.text, otherwise it returns nothing.Is there a simple way to write a check statement to make sure I can display both types of objects?
<td><a ng-href="{{item.job.href}}" target="_blank">{{item.job.text}}</a></td>
Use a ternary:
{{item.job.text ? item.job.text : item.job}}
You should try and normalize your data struct a bit - seems odd that job may contain an object or a simple text field.
I'm calling an api for the history of an ID which returns a string object that looks like this:
09304790130000--09304790090000
09304790130000--09304790120000
09304790090000--09304790010000
09304790120000--09304790020000
09304790120000--09304790030000
09304790120000--09304790110000
09304790110000--09304790050000
09304790010000--042322003
09304790020000--042322002
09304790030000--042322001
09304790050000--042322004
I could do so much more with it if I could figure out how to use JavaScript to convert it to JSON so it would look like this:
{
"name": "09304790130000",
"children": [{
"name": "09304790090000",
"children": [{
"name": "09304790010000",
"children": [{
"name": "04 2322-003"
}]
}]
}, {
"name": "09304790120000",
"children": [{
"name": "09304790020000",
"children": [{
"name": "04 2322-002"
}]
}, {
"name": "09304790030000",
"children": [{
"name": "04 2322-001"
}]
}, {
"name": "09304790110000",
"children": [{
"name": "09304790050000",
"children": [{
"name": "04 2322-004"
}]
}]
}]
}]
}
Is there an algorithm I can use that can construct the object I need regardless of how complicated the "tree" becomes?
EDIT for clarity:
The "--" in the string represents the relationship of the ID's. The left ID is the parent of the ID right of the dashes. So the ID that I feed the api, "09304790130000" has two children, each could have more children until they reach the current 9-digit ID.
What you have here is an input that is in a custom format. What you need to handle it is a regular expression. (Although your format might be simple enough that a full on regex function is not required so much as splitting on separators?) You need to do is break the input string up and loop over the components and put those into your desired data structure (which sounds like it would be some kind of tree). The high level pseudo-code would be something like:
Take line of input.
Break on "--".
Create root node from the left side if the tree is empty, otherwise just find the existing node.
Add child from right side to the parent.
Getting it into the JSON format you want may require also writing a function that iterates over the tree and writes a string in that format... although if you are using existing libraries and data types this probably already exists.
EDIT: To expand on the last bit, to get the format you want would mean a Pre-order traversal of the tree. At each step you just add the formatting and name to the JSON String. One of these libraries should have the capabilities you need, although obviously you can write a tree data structure and traversal function yourself if you need to.
I'm quite new to programming and I been googling but couldn't find exactly what I'm looking for.
ok I send a request by ajax and I get response similar to this (the original json is much more complicated)
{
"shelf": {
"genre": {
"title1": {
"date": "date",
"author": "name",
"featured": "N"
}
"title2": {
"date": "date",
"author": "name",
"featured": "Y"
}}}
now I need to do find a "book" which is featured. So I have been looking for a way to look for featured = Y and get it's title in this case "title2".
The best way I could figure out is that when I create the json (in php) when something is featured I can create a new key => value at the same level as "shelf"
"shelf": {
"genre": {
"title1": {
/.../
}
"title2": {
/.../
}}}
"featured": {
"genre": "featuredTitle"
"genre2":"featuredTitle2"
}}}
and then access it in javascript like this:
response.featured['genre'];
and then get all the data by going to
response.shelf.genre.title
but there must be a better way to do it... this gets very messy when the json is very complicated.
Thanks,
Tom
Almost there. You can loop through a JSON object quite easily, JSON is a very friendly format.
var genres = response.shelf.genre;
for (title in genres) {
if (genres.hasOwnProperty(item)) {
var bookTitle = title;
var featured = genres[title].featured;
}
}
The hasOwnProperty is a safety feature you should always use when looping through a JSON object. You can find out more about it here.
More on JSON
JSON solely consists of Javascript Objects and Arrays, one or the other. So even if the stack is complicated, you can always parse it by traversing either an object or an array, and so long as you know the structure of the JSON, it is easy to parse.
// Objects:
myJSON.subObject.anotherSubobject.andAnotherOne;
// Arrays:
myJSON[0]; // accesses first item in array...
myJSON.subObject[2]; // accesses third item in the subObject array.
I have a json output that looks like this.
{
"38467": {
"name": "Tony Parker",
"book": [
{
"title": {
"name": "MediaWorks"
},
},
],
}
"59678": {
"name": "Ray Thomas",
}
}
Actually json output is a lot bigger list. But I want to only save author's name and their publisher. I want save multiple individual records for a single model.
I am using jquery to assign input elements their values.
$('#Author' + i + 'Title').val(response...);
But it is not working.
I appreciate any help.
Thanks.
JSON is just javascript data - a javascript object. Assign the "decoded" JSON data to a variable (say var dat), then you can access members the normal object/array away: dat[38467]['name'] is Tony Parker and so on.
comment update:
once you've decoded/stored the data, you can use a regular javascript foreach loop to go over it:
for (var bookID in booklist) {
var author = booklist[bookID]['name'];
var title = booklist[bookID]['book'][0]['title']['name'];
// ...do stuff here...
}
There's nothing magical about JSON, it's just javascript data packed up for easy/clean transmission. Of course, if you're using a framework such as jQuery or MooTools, you'd be better off using their own .each() operators, otherwise you'll get various bits of useless fluff from the for() loop.
edit: fixed code sample as per marimuthu's comment (good catch, thanks).