admin管理员组

文章数量:1025244

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 both sub2 and sub3 properties? – guest271314 Commented Oct 5, 2016 at 5:27
  • because it's the question – Jaromanda X Commented Oct 5, 2016 at 5:34
Add a ment  | 

2 Answers 2

Reset to default 9

You 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));

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 both sub2 and sub3 properties? – guest271314 Commented Oct 5, 2016 at 5:27
  • because it's the question – Jaromanda X Commented Oct 5, 2016 at 5:34
Add a ment  | 

2 Answers 2

Reset to default 9

You 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));

本文标签: javascripthow to split key with dot to recovery json structureStack Overflow