Here is my JSON file below. Each object in the array belongs to an Id. So the first object would be #one, second object would be for #two. and so on. I can not figure out how to write this in JavaScript. How can I target which array number[1] with object[1] appends to #two for example? Also I need to delete the first line of the object which is the count line? Thank you!
so to get more into details. I was given an assignment, where I have placed pictures in the html and underneath the pictures, each object in the json file(description for the pictures) is supposed to go underneath it. I am new wtih json and ajax :( so the ids #one, #two... were just examples. There would be 6 ids. one for each object.
[
[
{
"count": "80",
"countTxt":"Buyer logins",
"participantsTxt":"Total for all participating member companies:",
"participantCount":"523"
},
{
"count": "233",
"countTxt":"Searches",
"participantsTxt":"Total for all participating member companies:",
"participantCount":"628"
},
{
"count": "533",
"countTxt":"Views of our member pages",
"participantsTxt":"Total for all participating member companies:",
"participantCount":"2,365"
}
],
[
{
"count": "80",
"countTxt":"Total vists",
"participantsTxt":"Total for all participating member companies:",
"participantCount":"412"
},
{
"count": "53",
"countTxt":"Unique visitors",
"participantsTxt":"Total for all participating member companies:",
"participantCount":"731"
},
{
"count": "1:12 min",
"countTxt":"Total time spent on page",
"participantsTxt":"Total for all participating member companies:",
"participantCount":"784.2 mins"
}
]
]
You have an array containing arrays which contain objects. They don't appear to have those IDs in them anywhere, and with names like #one, #two, and such, it's awkward to assign those (you basically have to have a list of names waiting to be assigned).
The work itself is relatively simple once you have that list:
Parse the JSON into an object graph via JSON.parse.
var outerArray = JSON.parse(jsonText);
Create a blank object you can save the named objects to as properties, like a map:
var map = {};
Type in your list of IDs as an array:
// This assumes no more than 99 elements
var ids = [
"#one", "#two", "#three", /*...and so on...*/, "#ninety-nine"
];
Have an index variable that starts with 0.
Loop through the outermost array; you have lots and lots of options for how to do that, I'd probably use forEach:
outerArray.forEach(function(nestedArray) {
// ...more code here
});
Inside that loop, loop through the objects in the nested array:
outerArray.forEach(function(nestedArray) {
nestedArray.forEach(function(object) {
// ...more code here
});
});
Inside the inner loop, add the current object to your map using the next available ID via your index variable:
map[ids[index++]] = object;
If you really want to, remove the count property from the object:
delete object.count;
So putting it all together:
var index = 0;
var outerArray = JSON.parse(jsonText);
var map = {};
var ids = [ // This assumes no more than 99 elements
"#one", "#two", "#three", /*...and so on...*/, "#ninety-nine"
];
outerArray.forEach(function(nestedArray) {
nestedArray.forEach(function(object) {
map[ids[index++]] = object;
delete object.count; // Doesn't matter whether this is before or after the line above
});
});
Notes:
It's going to be really awkward to access those objects with IDs like #one and such, but I assume you have a reason for it. You do map["#one"] and such to get at the objects.
If you don't have to delete the count property, don't bother.
First, you might want to ask yourself if your current way of formatting the data is appropriate. Currently, your data is formatted like this:
var jsonObject =
[
[{},{},{}],
[{},{},{}]
];
Where you have an outermost array, that contains two arrays, and the json data/javascript objects are then stored inside of those arrays. There probably isn't a need for the outermost array, and it would simplify the way you access the data inside of your json object without it. So keep in mind that all the examples you get here on SO are going to refer to the JSON object as you presented it.
// List off all "countTxt" objects to demonstrate how to
// iterate over a json object that contains nested
// arrays containing data. In your example, you have two arrays
// that each contain json data.
for (var i in jsonObject) {
for (var j in jsonObject[i]){
console.log(jsonObject[i][j].countTxt);
}
}
The above loop will print out the following:
/*
Unique visitors
Total time spent on page
Buyer logins
Searches
Views of our member pages
Total vists
Unique visitors
Total time spent on page
*/
Warning: as T.J. Crowder pointed out, using for..in loops to access json data will come back to bite you, so using this type of for..in looping structure (above) isn't recommended in production code, but it serves as a simple demonstration how you use access notation [] to grab values from an array of data objects. To read up on some best practices, you can read T.J. Crowder's in-depth post on the subject here.
If you want to target a specific item in the jsonObject, you do so like this:
// Grab the second object in the data array:
var secondObjectInJsonData = jsonObject[1];
console.log(secondObjectInJsonData);
// secondObjectInJsonData -> [Object, Object, Object]
If you want to grab specific data inside the data array:
// Grab the second object, inside the first array of json data
var countTxtOfSecondObject = jsonObject[0][2].countTxt;
console.log(countTxtOfSecondObject);
// countTxtOfSecondObject --> "Views of our member pages"
To Delete an object, you can use the delete command
var someObject = jsonObject[1][2];
delete someObject.count;
console.log("someObject after 'count' has been deleted: ", someObject);
Here is a JSFiddle to see all this code in action. Just open up the console in Chrome Developer Tools (in the Chrome browser) to see the output of all the console.log() statements.
First of all, You should reformat your data, Try using JSON Editor Online, this shows a tree view of your data. Chrome Extension is available for this, Please check the Chrome web store. It's a really good practice.
I've reformatted your data and made it into something which is more readable. Take a look;
[
{
"count": "80",
"countTxt":"Buyer logins",
"participantsTxt":"Total for all participating member companies:",
"participantCount":"523"
},
{
"count": "233",
"countTxt":"Searches",
"participantsTxt":"Total for all participating member companies:",
"participantCount":"628"
},
{
"count": "533",
"countTxt":"Views of our member pages",
"participantsTxt":"Total for all participating member companies:",
"participantCount":"2,365"
},
{
"count": "80",
"countTxt":"Total vists",
"participantsTxt":"Total for all participating member companies:",
"participantCount":"412"
},
{
"count": "53",
"countTxt":"Unique visitors",
"participantsTxt":"Total for all participating member companies:",
"participantCount":"731"
},
{
"count": "1:12 min",
"countTxt":"Total time spent on page",
"participantsTxt":"Total for all participating member companies:",
"participantCount":"784.2 mins"
}
]
You can access the JSON data using jQuery.getJSON() method and use jQuery.each method to loop through the object. Try this out;
$.getJSON('data.json', function(data) {
$.each(data, function(k) {
console.log(data[k]);
});
});
Check the console (ctrl+shift+j).
Now you can easily access the string. For eg;
console.log('Count: ' + data[k]['count']); //Displays all the count.
Hope you got some idea, You can play around with the JSON object like this and correct me if I'm wrong. Thank You
You can access the properties as below
json[0][0]["count"]
If you want to delete a property use
delete json[0][0]["count"]
Fiddle http://jsfiddle.net/wa99rxgL/
Related
I'm not looking for the keys that this object contains but the key of the object itself (the key in the array containing the object).
I have this JSON:
{
"Object name (text)": {
"raw": "Some more text.",
},
"Another name": {
"raw": "Some other text.",
}
}
and would like to get "Object name (text)" for the first item.
My Vue code is:
<CustomComponent
v-for="object in objects"
:key="getKey(object)"
:object="object"
/>
I'm not sure if the getKey-method approach is how one is intended to get unique identifiers for iterating through the JSON array. Its code currently is:
getKey(object) {
return Object.keys(object)[0];
}
Now I'd like to somehow pass the name of the object to the CustomComponent ("Object name (text)" in the first case).
One temporary workaround that I intended to use until I find something more appropriate was getting the keys from the objects array like so:
:objectName="getObjectName(object)" and itemNumber: -1 in data and this method:
getObjectName(object) {
this.itemNumber = this.itemNumber + 1;
var objectName = Object.keys(this.objects)[this.itemNumber];
console.log("Object name: ", objectName);
}
However, the first line of this method causes it to run hundreds of times instead of only two times (why is that?; it works in the first 2 executions of the method and when commenting out that line) and I think this is unlikely the proper method to simply retrieve the object's name/key.
It also didn't work when putting the above code into the getKey method which would make more sense (and I had the code in that method before creating a separate method to debug). Then the key could be accessed in the component with this.$vnode.key However, it keeps being undefined. This might be a separate problem even though it could resolve this problem here as well - I might create a new question for it. It enters the methods "getKey" and "getObjectName" 6 times each even though it only renders two items on the page, like it should.
-> How to get the JSON object's key in JavaScript?
(Preferably from the object itself after iterating through a JSON array with a loop with Vue instead of only indirectly by checking the objects array.)
Edit: as a workaround I have now done this:
var keys = Object.keys(this.objects);
keys.forEach(element => {
this.objectsWithKeys.push({
object: this.objects[element],
key: element
});
});
<CustomComponent
v-for="objectWithKeys in objectsWithKeys"
:key="objectWithKeys.key"
:object="objectWithKeys.object"
>
</CustomComponent>
this.$vnode.key
This is solved, I used var objectsWithKeys = data[Object.keys(data)]; and {{ $vnode.key }}.
Basically I'm doing practice exercises where I need to list the properties of an object, and I've done this:
/* Write a JS program to list the properties of a JS object*/
console.log("EX 1");
let student = {
name: "Dollar",
job: "Unemployed",
age: 18
};
let listing = Object.getOwnPropertyNames(student); // lists the properties of a JS object
console.log(listing.toString());
The output seems correct, but when I go to the resolution, it uses functions and if statements(if needed I'll provide them).
Is anything wrong with my code?
In your example code, listing is already a list of the properties of the object, meaning the names of the keys of all key-value pairs in the dict-like structure.
There doesn't seem to be a good reason to use .toString() to convert the list itself into a string.
The goal of the comment "Write a JS program..." is probably simply to get you to write a for-loop to loop through the object, which is iterable.
for (let item of obj1) {
console.log(item);
}
Using const token = response.json().token; I am able to get the following JSON:
{
"token": "*********",
"roles": [
{
"id": 4,
"name": "User",
"pivot": {
"user_id": 1,
"role_id": 4
}
}
]
}
I want to be able to access the names within the roles as an array.
If you just want to access the array of roles, assuming you're using a traditional response object, you can just access it the way other users have stated:
var roles = response.json().roles
As I reread the question and comments, I get the idea that the user wants to access the names within the roles as as list. Assuming so, the map function will do this nicely:
// Assuming we store response in "data"
var data = response.json();
var names = data.roles.map(function(role){return role.name});
console.log(names);
// Then "names" will look like ["User",...]
In a nutshell, map will walk the array it's called against and run the provided function against it, with the first argument being the current value it sees in the array. This function can be defined on the fly as above, or predefined and passed if the logic is complex or reused.
This is a very common use for Map, and its sibling, Reduce. Both are often used for distilling complex, variable-length data down to a simpler form.
Map documentiation:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
Update: It would appear the original question was asked regarding ES6, so here's the "proper" ES6 version with proper declarations and arrow funcs:
// Assuming we store response in "data"
const data = response.json();
const names = data.roles.map(role => role.name);
console.log(names);
// Then "names" will look like ["User",...]
I'm trying to generate a tree structure in JavaScript from a flat array. This would usually be a fairly straightforward proposition - simply retain a 'stack' array with references to ancestor objects of the current working scope ordered by nesting depth - push a new element onto the stack when entering another nested level, and pop it off when leaving one, replacing the current working element with the object referenced by the (new) last array item.
Unfortunately this requires the capability to pass-by-reference, which JavaScript doesn't have (well, doesn't have in any meaningful way that I know how I could use for this problem.)
To give a bit of background, I'm trying to turn an arbitrarily long/complicated string containing nested XML-style (but not XML, so an XML parser can't be used instead) tokens into a structure similar to the one below:
Expected Input:
[
"<token>",
"<my non compliant token>",
"some text at this level",
"<some other token>",
"some more text",
"<yet another token>",
"more text",
"</yet another token>",
"blah!",
"</some other token>",
"</token>",
"more text"
]
Expected Output
[
{
"token": "<token>",
"children": [
{
"token": "<my non compliant token>",
"children": [
"some text at this level",
{
"token": "<some other token>",
"children": [
"some more text",
{
"token": "<yet another token>",
"children": [ "more text" ]
},
"blah!"
]
}
]
}
]
},
"more text"
]
To clarify - I'm not after an entire algorithm (but I'd be interested if you want to provide your implementation) - just a good method for maintaining current position in the outputted tree (or an entirely different/better way of generating tree objects!) Don't get too caught up on how the tokens work - they're not XML and for the purpose of the exercise could be formatted entirely differently.
Any input would be greatly appreciated!
Your strings look easy to parse. I think I would do something like this:
var stack = [];
var array = [];
for (var i in strings) {
var s = strings[i];
if (s.indexOf("</") == 0) {
array = stack.pop();
} else if (s.indexOf("<") == 0) {
var obj = {token: s, children: []};
array.push(obj);
stack.push(array);
array = obj.children;
} else {
array.push(s);
}
}
Idea #1
Here's an answer you probably weren't anticipating.
Looking at your expect output, I was wondering if it's easiest to just generate JSON and then eval it when you're done. No references at all.
When going through your flat array, you basically have three operations:
You add more data to the current object
You close off the current object
You create a new child object
You can do all three of those fairly easily by just appending the appropriate text onto a JSON string you're building as you iterate through your source array to literally just generate the text you show in your expected output. When done, run that JSON string through eval. You may need a few safety checks to verify that each array and object is closed properly if there are errors in the input, but it should work fine.
Idea #2
You can still use your stack array. I'm not sure exactly why you need to pass by reference, but you can just pass an index into the array around and have everyone modify the master copy of the array that way via index. Using local functions, the master array can be a common data value that is local to your main function, but essentially global to all your sub-functions so they can all shared access to it.
This would look something like this:
function ParseRawData(rawData)
{
var parentScopeArray = []; // main parent scope of objects
function processTag(x)
{
// you can access parentScopeArray directly here and
// and be accessing it by reference
}
// other code or local functions here
}
Idea #3
If you want to pass the array into a function and have the master copy modified (perhaps the reason you're thinking of pass by reference), the javascript design pattern is to pass the array in and return a modified array, replacing the entire original array with the modified one that is returned.
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).