I have a json, it is
{
"prop1.sub1.sub2": "content1",
"prop1.sub1.sub3": "content2",
"prop2.sub1.sub2": "content3",
"prop3.sub1.sub2": "content4"
}
I want to recovery the structure, like
{
"prop1": {
"sub1": {
"sub2" : "content1",
"sub3" : "content2"
}
},
"prop2": {
"sub1": {
"sub2" : "content3"
}
},
"prop3": {
"sub1": {
"sub2" : "content4"
}
}
}
I split the key with dot to get each key.
for (var key in json) {
var keySplit = key.split('.');
// Todo: recovery the structure
}
But not found a good solution.
Is anyone has solution?
I have a json, it is
{
"prop1.sub1.sub2": "content1",
"prop1.sub1.sub3": "content2",
"prop2.sub1.sub2": "content3",
"prop3.sub1.sub2": "content4"
}
I want to recovery the structure, like
{
"prop1": {
"sub1": {
"sub2" : "content1",
"sub3" : "content2"
}
},
"prop2": {
"sub1": {
"sub2" : "content3"
}
},
"prop3": {
"sub1": {
"sub2" : "content4"
}
}
}
I split the key with dot to get each key.
for (var key in json) {
var keySplit = key.split('.');
// Todo: recovery the structure
}
But not found a good solution.
Is anyone has solution?
Share Improve this question asked Oct 5, 2016 at 5:24 Peace PanPeace Pan 3934 silver badges15 bronze badges 3-
1
Todo: recovery the structure
- have you tried anything - you're on the right path – Jaromanda X Commented Oct 5, 2016 at 5:25 -
Why does
prop1.sub1
contain bothsub2
andsub3
properties? – guest271314 Commented Oct 5, 2016 at 5:27 - because it's the question – Jaromanda X Commented Oct 5, 2016 at 5:34
2 Answers
Reset to default 9You can use Array#reduce
method.
var obj = {
"prop1.sub1.sub2": "content1",
"prop1.sub1.sub3": "content2",
"prop2.sub1.sub2": "content3",
"prop3.sub1.sub2": "content4"
};
// iterate over the property names
Object.keys(obj).forEach(function(k) {
// slip the property value based on `.`
var prop = k.split('.');
// get the last value fom array
var last = prop.pop();
// iterate over the remaining array value
// and define the object if not already defined
prop.reduce(function(o, key) {
// define the object if not defined and return
return o[key] = o[key] || {};
// set initial value as object
// and set the property value
}, obj)[last] = obj[k];
// delete the original property from object
delete obj[k];
});
console.log(obj);
Answer by Pranav C Balan is right for the question you asked. But JSON's might not be as simple as you have mentioned above and can have array's also and few keys might not have "." in them. To handle all these cases you can use the following one.
var obj = {
"prop1.sub1.sub2": "content1",
"prop1.sub1.sub3": "content2",
"prop2.sub1.sub2": "content3",
"prop3.0.sub2": "content4"
};
function createJSONStructure(obj) {
Object.keys(obj).forEach(function(k) {
var prop = k.split('.'); //split on . to get elements
if(prop.length >1){ //If there is no dot just key the value as is.
let data = obj;//Copy the default object to data in each loop
for(i=0;i<prop.length-1;i++){
if(data[prop[i]]){ // Check if the key exists
if((prop[i+1].match(/^\d+$/) && !Array.isArray(data[prop[i]])) // Check if the next key is a digit and the object we have is a JSON
|| (!prop[i+1].match(/^\d+$/) && Array.isArray(data[prop[i]]))){ // Check if the next key is not a digit and the object we have is a Array
throw new Error("Invalid header data"); //If any of the above cases satisfy we cannot add the key so we can throw an error.
}
data = data[prop[i]]; // If key exisits make the data variable as the value of the key
}else {
if(prop[i+1].match(/^\d+$/)){ //If the key is not available see if the next parameter is a digit or string to decide if its array or string
data[prop[i]] = [];
}else{
data[prop[i]] = {};
}
data = data[prop[i]]; //Assign this new object to data
}
};
data[prop[i]] = obj[k]; //Finally add the value to final key
delete obj[k]; // delete the exisiting key value
}
});
return obj;
}
console.log(createJSONStructure(obj));