Iterating through a nested JSON tree and changing values
I have a JSON tree with the following structure:
{
"projects": {
"Proj1": {
"milestones": {
"default": "20150101",
"default2": "20140406",
"default3": "20140101",
"default4": "20131231",
"default5": "20131220"
}
},
"Proj2": {
"milestones": {
"default": "20131231",
"default2": "20131220"
}
}
}
}
I have a code to read it in a webpage, with the "default" part in the text and numbers / dates in the textbox / form. The idea is that you can change the dates and send, which goes to the backend and is written to a file. This all works for the most part. I can figure out how to iterate through the JSON tree I have and write new values. For example:
Accessing JSONTREE.projects.Proj1.milestones.default returns the value for this key. Setting a value with this call changes the value accordingly. What I want to do is iterate over the entire tree and set the default values ββdepending on what is in the form window. I have it:
$.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, although "alert (date)" returns a value. I suspect this is because it is a value and not an object reference, but how can I get to the object? I suspect it is simple, but I am not a jQuery / JS pro.
TL; DR How do I get references to a key in a nested JSON tree to change the value?
EDIT: Ok I think this is what I need: JS / Jquery - using a variable in a json selector . I changed the "date" part to: formJSON.projects [projectName] [select] [milestones] = document.getElementById (saltKey) .value; which seems to work.
source to share
Your edit to the passed value, not the original JSON object.
One way to fix this is to create a new JSON object, build as you iterate over the existing one, and then overwrite the original, or use the new JSON object.
Another is to create a var that stores the original JSON object and either pass it through your functions or access it directly inside the functions.
source to share
I faced the same problem and this is my solution for iterating over a JSON object (MongoDB) and modifying certain elements regardless of whether those object properties or properties are an array with a lot of objects. I know the question is old, but it might be helpful to someone. Assuming we have such an object or even more complex one.
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 it is or what constructor our data has.
// 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 the third iteration over the element, regardless of whether it is an object or an 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 that we should use to replace our string.
function replaceElement(element){
if(element === "blue"){
return "Blue is the warmest color"
}else{
return element;
}
}
And finally, we get the result:
console.log(iterate(mixData));
Result:
{
"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 replacement function according to your needs. And, of course, delete all console logs.
source to share