Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I get below Array of JSON objects from JSP
"Titles":[
{
"Book3" : "BULLETIN 3"
}
,
{
"Book1" : "BULLETIN 1"
}
,
{
"Book2" : "BULLETIN 2"
}
]
On JS side, it is parsed and I see an array with 3 objects.
Now, I want to find/identify a value when I pass String key.
For e.g. when I pass "Book2" I should get value "BULLETIN 2".
Can someone help me identify the approach?
Try this
var data = {
"Titles": [{
"Book3": "BULLETIN 3"
}, {
"Book1": "BULLETIN 1"
}, {
"Book2": "BULLETIN 2"
}]
};
function getValueByKey(key, data) {
var i, len = data.length;
for (i = 0; i < len; i++) {
if (data[i] && data[i].hasOwnProperty(key)) {
return data[i][key];
}
}
return -1;
}
console.log(getValueByKey('Book2', data.Titles));
Having:
var x = [{
"Book3" : "BULLETIN 3"
}, {
"Book1" : "BULLETIN 1"
}, {
"Book2" : "BULLETIN 2"
}];
and
var key = "Book1";
You can get the value using:
x.filter(function(value) {
return value.hasOwnProperty(key); // Get only elements, which have such a key
}).shift()[key]; // Get actual value of first element with such a key
Notice that it'll throw an exception, if object doesn't have such a key defined.
Also, if there are more objects with such key, this returns the first one only. If you need to get all values from objects with such key, you can do:
x.filter(function(value) {
return value.hasOwnProperty(key); // Get only elements, which have such a key
}).map(function(value) {
return value[key]; // Extract the values only
});
This will give you an array containing the appropriate values only.
Additionally, if you're using jQuery, you can use grep instead of filter:
jQuery.grep(x, function(value) {
return value.hasOwnProperty(key);
}) /* and so on */;
To achieve this, you have to loop through the array elements's keys and test if the given key exists in the array, if so get its value:
var jsonTitles = [
{ "Book3" : "BULLETIN 3" },
{ "Book1" : "BULLETIN 1" },
{ "Book2" : "BULLETIN 2" }
]
function getValue(key, array) {
for (var el in array) {
if (array[el].hasOwnProperty(key)) {
return array[el][key];
}
}
}
alert(getValue("Book1", jsonTitles));
We use element[key] where element is array[el] to get the value of the given key.
Let's create a function to get an object in an array for that, that takes two arguments: the array and the key of the property you want to get:
function getObjectInArray(arr, key) {
for (var i = 0; i < arr.length; i++) {
if (arr[i].hasOwnProperty(key)) return arr[i][key];
}
}
This loops through each object looking for that specific key.
Solution: Now you could do something like getObjectInArray(titlesJSONArray, "Book2") and it should return "BULLETIN 2".
var titlesJSONArray = [ { "Book3": "BULLETIN 3" }, ... ]; // and so on
var book2 = getObjectInArray(titlesJSONArray, "Book2"); // => "BULLETIN 2"
For such array/collection manipulation in Javascript I would suggest you to use underscorejs library. It provides functions that, to me, make everything much more simple. In your case:
function find_value(array, key) {
// find will run the provided function for every object in array
var obj_found = _.find(array, function(obj) {
// keys returns the keys inside an object
// so if the key of currently examined object
// is what we are looking for, return the obj
if (_.keys(obj)[0] === key) {
return obj;
}
});
// if an object with such key was found return its value
if (obj_found) {
return obj_found[key];
} else {
return null;
}
}
Here is a working fiddle of what I am suggesting.
Related
This question already has an answer here:
Index an array of arrays with an array of indexes in javascript
(1 answer)
Closed 2 years ago.
I have a Json file with an unknown depth of nested children, and i need to read that with javascript, and delete an element somewhere within the object. I have the path of the child to delete stored in an array called nestPath (example [0,0,3] where the path would be [0]->[0]->[3]). The problem is that i do not know how to dynamically target the object directly without using a variable to reference the Json object, but if i try to delete the variable it will only delete the reference, not the actual object within the Json.
I would like to dynamically access it with the path given by nestPath so that with an input of [0,1,2,3], i would be able to access: jsonObject[0][1][2][3] without using a variable, so that i can delete it.
The code i tried:
var nestPath = [0,0,1];
var stateObject = menuToolState['menu'];
for (var i = 0; i < nestPath.length; i++) {
if (i > 0) {
stateObject = stateObject['links'][nestPath[i]];
} else {
stateObject = stateObject[nestPath[i]];
}
}
delete stateObject;
menuToolState:
{
"menu": [
{
"name": "0",
"links": [
{
"name": "0-0",
"links": [
{
"name": "0-0-0",
"links": []
},
{
"name": "0-0-1 (delete this)",
"links": []
}
]
}
]
}
]
}
With this code i am able to access the information within the object, but i am not able to delete it as delete just deletes the reference. How can i achieve this?
Right, so to delete a property on an object you need to call delete on the direct holder of that property. E.g. if you want to delete a property ['nestedProp'] inside an object
{prop1: {prop2: {nestedProp: 'hello'}}}
you need to keep a reference to the actual object holding it. Which will be obj['prop1']['prop2'].
const someNestedObj = {
prop1: {
prop1_1: {nested1: 'hello'}
},
prop2: {
prop2_1: {nested1: 'world'}
}
};
function deleteProp(obj, propPath) {
let curObj = obj;
let parentObj = obj;
for (let prop of propPath) {
parentObj = curObj;
curObj = curObj && curObj[prop];
}
if (propPath[propPath.length - 1] in parentObj) {
delete parentObj[propPath[propPath.length - 1]];
} else {
throw new Error('No such property');
}
}
deleteProp(someNestedObj, ['prop1', 'prop1_1', 'nested1'])
console.log(someNestedObj);
I am trying to get a value from an array within an object.
This is the data:
{
"Order Number":102541029,
"Tracking Number":192048236154915,
"Secondary Tracking":87350125235,
"Items":[{
"SKU":"0200-02-01-NP-P-00",
"QTY":4
},
{
"SKU":"0120-02-01-XP-T-00",
"QTY":2
}]
}
If I wanted, say, the quantity of the second item (SKU 0120-02-01-XP-T-00), how would I select this?
I've tried a few things like this:
var skuQty = datain.items.['0120-02-01-XP-T-00'].['QTY'];
That's the idea, but I am not using the right syntax obviously. Any help here?
Jesse
This is how you scroll through the quantities:
var yourObject = {
"Order Number":102541029,
"Tracking Number":192048236154915,
"Secondary Tracking":87350125235,
"Items":[{
"SKU":"0200-02-01-NP-P-00",
"QTY":4
},
{
"SKU":"0120-02-01-XP-T-00",
"QTY":2
}]
};
var items = yourObject.Items;
for (var i = 0; i < items.length; i ++){
console.log(items[i].QTY);
}
In general you can access an array with its index something like this: arr[i] and object can be accessed by it's key name:
`yourObject.yourkey`
in JavaScript, an array = [1,2,3] can be accessed with array[index].
If you have an array that looks like this: array = [{ prop: propValue }], then this is virtually the same as obj = { prop: propValue }; array = [ obj ], so what you need to do to get propValue is array[ 0 ]['prop'].
For your specific case, you'd need
datain.Items[1]['SKU'];
Now, what you actually want to do is filter through the array items until the above value is "0120-02-01-XP-T-00"
This is literally filtering an array:
datain.Items.filter( function( obj ){ return obj['SKU'] === "0120-02-01-XP-T-00" } )[0]['QTY']
The key is that array.filter( fn ) returns a new array of values for which fn( item [, other parameters you don't need to worry about] ) is true (or truthy). At that point, you only need the first item, at index = 0
First of all, select the specified object - in your case - data.
Then select specified key from the data object - in your case - Items.
Since Items is an array with two objects, you have to specify which one of them you are interested in. In your case - the second one with index 1.
data.Items[1] is an object holding two positions. You are interested in the second one - so you just type that key name - QTY.
Adding it up together - data.Items[1].QTY.
var data = {
"Order Number": 102541029,
"Tracking Number": 192048236154915,
"Secondary Tracking": 87350125235,
"Items": [{
"SKU": "0200-02-01-NP-P-00",
"QTY": 4
}, {
"SKU": "0120-02-01-XP-T-00",
"QTY": 2
}]
};
console.log(data.Items[1].QTY)
This is how you get it:
Object {Order Number: 102541029, Tracking Number: 192048236154915, Secondary Tracking: 87350125235, Items: Array[2]}
obj.Items[0]
Object {SKU: "0200-02-01-NP-P-00", QTY: 4}
obj.Items[0].QTY
obj = {
"Order Number":102541029,
"Tracking Number":192048236154915,
"Secondary Tracking":87350125235,
"Items":[{
"SKU":"0200-02-01-NP-P-00",
"QTY":4
},
{
"SKU":"0120-02-01-XP-T-00",
"QTY":2
}]
};
console.log(obj.Items[0].QTY);
You can use Array.prototype.filter(), at callback return o.SKU === "0120-02-01-XP-T-00", where o is current object in iteration use bracket notation to select element at index 0 of returned array
var QTY = data.Items.filter(function(o) {
return o.SKU === "0120-02-01-XP-T-00"
})[0]["QTY"];
You can alternatively utilize destructuring assignment
var [, {QTY}] = data.Items;
Because items is an array, you need to select the appropriate index of the array, in this case 1.
For example:
var skuQty = datain.items[1].QTY;
Make a function to find order items for a given SKU:
var findOrderItem = function (order, sku) {
if (order && order.Items) {
for (var i = 0; i < order.Items.length; i++) {
if (order.Items[i].SKU == sku) {
return order.Items[i];
}
}
}
return null;
};
var myOrder = {
"Order Number": 102541029,
"Tracking Number": 192048236154915,
"Secondary Tracking": 87350125235,
"Items": [
{
"SKU": "0200-02-01-NP-P-00",
"QTY": 4
},
{
"SKU": "0120-02-01-XP-T-00",
"QTY": 2
}
]
};
var sku = "0120-02-01-XP-T-00";
var item = findOrderItem(myOrder, sku);
var qty = 0;
if (item) {
qty = item.QTY;
}
console.log("item qty", qty);
I am trying to delete property from objects which is present in array .Actually In my objects, each object contain a property shortkeys .I need to delete shortkeys property only when it not present in given object .In other words
I have one given object
var obj ={
alt+c:"alt+c"
alt+g:"alt+g"
}
I need to delete shortkey property from object only if it not present in given object key .
I tried like this
var arr=[
{name:"abc",shortkeys:"alt+m"},
{name:"abc",shortkeys:"alt+a"},
{name:"abc",shortkeys:"alt+c"},
{name:"abc",shortkeys:"alt+f"},
{name:"abc",shortkeys:"alt+g"}
]
var obj ={
alt+c:"alt+c"
alt+g:"alt+g"
}
for (var i=0;i<arr.length;i++){
var o =arr[i];
for(key in obj){
if(o.shortkeys !=key){
delete o.shortkeys;
}
}
}
Expected output
var expectedArr=[
{name:"abc"},
{name:"abc"},
{name:"abc",shortkeys:"alt+c"},
{name:"abc"},
{name:"abc",shortkeys:"alt+g"}
]
Fiddle
https://jsfiddle.net/5134enew/1/
Update :
It delete from all object
https://jsfiddle.net/5134enew/2/
Besides the syntax error, your code checks if there exists a key that is not the shortkey, rather than checking if the shortkey is in the list you want to check against. alt+c is checked against alt+g, and thus removed. You want to prevent deletion when it is found instead.
So instead of doing the following...
for(key in obj){
if(o.shortkeys !=key){
delete o.shortkeys;
}
}
...you would do this instead.
var match = false;
for (key in obj) {
if (o.shortkeys == key) {
match = true;
break;
}
}
if (!match) {
delete o.shortkeys;
}
This can be shortened to a simple x in y in check as #Mark Leiber suggested. You should realize that the deletion takes place after checking all keys, instead of deleting just whenever we encounter a key that does not match.
var arr = [{
name: "abc",
shortkeys: "alt+m"
}, {
name: "abc",
shortkeys: "alt+a"
}, {
name: "abc",
shortkeys: "alt+c"
}, {
name: "abc",
shortkeys: "alt+f"
}, {
name: "abc",
shortkeys: "alt+g"
}]
var obj = {
"alt+c": "alt+c",
"alt+g": "alt+g"
}
for (var i = 0; i < arr.length; i++) {
var o = arr[i];
if(!(o.shortkeys in obj)) {
delete o.shortkeys;
}
}
console.log(arr);
As said above your code deletes the shortkeys when it doesn't match with the keys in obj. So (o.shortkeys)"alt+m"!==(key)"alt+c"-->hence delete o.shortkeys.And then again it goes for checking (shortkey which has been already been deleted so o.shortkeys is undefined)ie "undefined != alt+g" which has got no meaning and again tries to delete o.shorkeys ie undefined which makes no meaning.
I have written a more detailed code similar to the above one.
please check the fiddle : jsfiddle.net/som99/d37ws7r6/2/
Explanation are given in comments.Check the console for the output.
What I have is a JSON tree of the following structure:
{
"projects": {
"Proj1": {
"milestones": {
"default": "20150101",
"default2": "20140406",
"default3": "20140101",
"default4": "20131231",
"default5": "20131220"
}
},
"Proj2": {
"milestones": {
"default": "20131231",
"default2": "20131220"
}
}
}
}
I have code to read it into a web page, with the 'default' part in text, and the numbers/dates in a text box/form. The idea is that you can change the dates and submit, which goes to the backend and gets written to a file. All that works for the most part. What I can figure out is how to iterate through the JSON tree I have and write the new values. For example:
Accessing JSONTREE.projects.Proj1.milestones.default returns the value for that key. Setting the value with that call changes the value appropriately. What I want to do is iterate through the entire tree and set the values of the 'defaults' based on whatever is in the form box. I have this:
$.each(formJSON.projects, function (projectName) {
$.each(this, function (selection) {
$.each(this, function (milestones, date) {
var saltKey = projectName + "-" + milestones;
date = document.getElementById(saltKey).value;
});
});
});
but it does nothing, even though 'alert(date)' returns a value. I suspect this is because it's the value, and not a reference to the object, but how can I get to the object? I suspect it's simple, but I'm not a pro with jQuery/JS.
TL;DR How do I get references to a key in a nested JSON tree so I can change the value?
EDIT: Okay, I think this is what I needed: JS/Jquery - using variable in json selector. I changed the 'date' portion to: formJSON.projects[projectName][selection][milestones] = document.getElementById(saltKey).value; which seems to work.
I ran into the same problem and this is my solution to iterate over a JSON object (MongoDB) and modify certain elements regardless of whether these are properties of the object or property is an array with more objects. I know the question is old, but it can be useful to someone.
Assuming we have an object like this or even more complex.
var mixData = {
"Hello": "World",
"Foo" : "Bar",
"sudo": [
{ "apt-get": "upgrade" , "force": false },
{ "apt-get": "update" , "force": true}
],
"colors": ["blue","green"],
"numbers":{
"integer": [
{"num": 1},
{"num": 2},
{"num": 3}
],
"operator": "addition"
}
};
And we want to replace some string (blue in this case), but we don't know where is or what kind of constructor has our data.
// Detect if the element is an Array
function isElementArray(element){
return (element.constructor === Array ? true : false);
}
//Detect if the element is an Object
function isElementObject(element){
return (element.constructor === Object ? true : false);
}
Now that we have these two functions, we use a third to iterate over the item, regardless of whether an object or array.
function iterate(element){
//Check if the element is an Object
if(isElementObject(element)){
for (var property in element){
if(isElementObject(element[property])){
element[property] = iterate(element[property]);
}else if(isElementArray(element[property])){
//An array
for(var x = 0; x < element[property].length; x++){
element[property][x] = iterate(element[property][x]);
}
}else{
if(element.hasOwnProperty(property)){
console.log("New object inside object property");
element[property] = iterate(element[property]);
}else{
element[property] = replaceElement(element[property].toString());
console.log("Single Element: " + element[property] )
console.log(element + " " + element[property]);
}
}
}
}else if(isElementArray(element)){
//An Array
for (var x = 0; x < element.length; x++){
element[x] = iterate(element[x]);
}
}else{
//Single element in array or property
element = replaceElement(element.toString());
console.log("Single Element : " + element);
}
return element;
}
And the function we need to use to replace our string.
function replaceElement(element){
if(element === "blue"){
return "Blue is the warmest color"
}else{
return element;
}
}
And finally, we can get the result:
console.log(iterate(mixData));
The result is:
{
"Hello": "World",
"Foo" : "Bar",
"sudo": [
{ "apt-get": "upgrade" , "force": false },
{ "apt-get": "update" , "force": true}
],
"colors": ["Blue is the warmest color","green"],
"numbers":{
"integer": [
{"num": 1},
{"num": 2},
{"num": 3}
],
"operator": "addition"
}
};
You can change the replace function to suit your needs. And of course, remove al the console logs.
Your editing the passed value and not the original JSON object.
One way to fix this is to create a new JSON object, build as you iterate through the existing one, and then overwrite the original or use the new JSON object.
Another is to create a var holding the original JSON object and either pass it through your functions or access it directly inside the functions.
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I have the following JSON object array in javascript :
[{ "AuthorName" : "Abc", "BookName" : "book-1" }]
[{ "AuthorName" : "Abc", "BookName" : "book-2" }]
[{ "AuthorName" : "Abc", "BookName" : "book-3" }]
[{ "AuthorName" : "Abc", "BookName" : "book-4" }]
Now I want to create a single JSON object from the above JSON objects array. The newly created single JSON object contains 2 properties: AuthorName and BooKName array. I am trying to achieve something like this:
{ "AuthorName" : "Abc", "Book" : ['book-1', 'book-2', 'book-3', 'book-4'] }
Now my question is, how can I achive this efficiently and with writing minimum code in javascript?
var obj = {};
for(var i=0; i<myArray.length; i++) {
if(obj[myArray[i].AuthorName] == null)
obj[myArray[i].AuthorName] = [];
obj[myArray[i].AuthorName].push(myArray[i].BookName)
}
Hopefully, this will help:
var bookSort = function (bookarray) {
var i,
book,
authorArray = [],
il = bookarray.length,
j,
jl,
authorInArray;
for (i = 0; i < il; i++) {
authorInArray= false;
jl = authorArray.length;
book = bookArray[i];
for (j = 0; j < jl; j++) {
if (book.AuthorName = authorArray[j].AuthorName) {
authorInArray= true;
authorArray[j].BookName.push(book.BookName);
break;
}
}
if (!authorInArray) {
authorArray.push({AuthorName: book.AuthorName, BookName: [book.BookName]});
}
}
return authorArray;
};
Seems like you need a function that combines multiple objects.
If you create a general purpose function that does this, you can reuse it. I would discourage you from creating a solution with things like authorArray etc hard coded into it.
Let's create a function that takes multiple objects and combines them. Let's keep it simple and assume the objects look like the ones from your question. In other words the objects to combine will simply be a flat list of name value pairs. The values will either be a string or an array of strings.
jsFiddle Demo
// A function that combines multiple object.
// The original objects are made of name value pairs where the values are strings.
// If - for a key - the values are the same, the value is kept
// If - for a kye - the values are different, and array is created and the values pushed to it
// after this all new values are added to the array if not already there.
var combineObjects = function() {
// see how many object are to be combined
var length = arguments.length,
i,
// Create a new empty object that will be returned
newObject = {},
objectIn,
prop,
temp,
ii,
alreadyExists;
// Go through all passed in object... combinging them
for (i = 0; i < length; ++i) {
objectIn = arguments[i];
for (prop in objectIn) {
if (objectIn.hasOwnProperty(prop)) {
// Check if the prop exisits
if (newObject[prop]) {
// Check if the prop is a single or multiple (array)
if (Object.prototype.toString.call( newObject[prop] ) === '[object Array]') {
// Multiple
// Check if element is in array
alreadyExists = false;
for (ii = 0; ii < newObject[prop].length; ++ii) {
if (newObject[prop][ii] === objectIn[prop]) {
alreadyExists = true;
break;
}
}
if (! alreadyExists) {
newObject[prop].push(objectIn[prop]);
}
} else {
// Single
if (newObject[prop] !== objectIn[prop]) {
temp = newObject[prop];
newObject[prop] = [temp, objectIn[prop]];
}
}
} else {
newObject[prop] = objectIn[prop];
}
}
}
}
// Alert for testing
alert(JSON.stringify(newObject));
return newObject;
};
It looks like those are just four seperate arrays containing objects.
If you put those four seperate arrays inside another array so they can be iterated, like so:
var a = [
[{ AuthorName : 'Abc', BookName : 'book-1'}],
[{ AuthorName : 'Abc', BookName : 'book-2'}],
[{ AuthorName : 'Abc', BookName : 'book-3'}],
[{ AuthorName : 'Abc', BookName : 'book-4'}]
];
I'd just do:
var new_array = [],
temp_obj = {};
$.each(a, function(i,e) {
var author = e[0].AuthorName,
book = e[0].BookName;
temp_obj[author] ? temp_obj[author].push(book) : temp_obj[author] = [book];
});
$.each(temp_obj, function(author,books) {
var obj = {AuthorName: author, BookName : books};
new_array.push(obj);
});
//new_array is now = [{ AuthorName : 'Abc', BookName : ['book-1', 'book-2', 'book-3', 'book-4'] }]
FIDDLE
and it would sort out more authors and books etc. aswell ?
PROOF
Not sure what you are after. Maybe this will work for you:
var books = [
[{ "AuthorName" : "Abc", "BookName" : "book-1" }],
[{ "AuthorName" : "Abc", "BookName" : "book-2" }],
[{ "AuthorName" : "Abc", "BookName" : "book-3" }],
[{ "AuthorName" : "Abc", "BookName" : "book-4" }]
];
// First book in the array
var first = books[0][0];
// Add BookName property to the first book object (BookNames would be a better name)
first.BookName = books.map(function(book, n) {
return book[0].BookName;
});
/*
Or, use jQuery.map if you got a older browser that don't support the Array.map function
$.map(books, function(book, n) {
return book[0].BookName;
});
*/
// first is now:
{ AuthorName : "Abc", BookName : ['book-1', 'book-2', 'book-3', 'book-4'] }