-1

I have an object as below:

var obj = 
{
  a : 
  {
    "x": "abc",
    "y": "def",
    "z": "ghi"
  },

 b : 
 {
   "p" : "jkl",
   "q" : "mno",
   "r" : "pqr"
 },
 ...
 ...
}

I want the output as below:

var targetObject = 
{
  "a_x":"abc",
  "a_y":"def",
  "a_z":"ghi",
..
..
..
..
}

There can be n number of key as well as hierarchy. Can we have a function where the input is the object and the output gives me that targetObject?

Heretic Monkey
  • 11,687
  • 7
  • 53
  • 122
us123133
  • 1
  • 2
  • This is a fairly specific requirement, such as the underscore between "a" and "x". I'm afraid there isn't going to be any "one function" that already exists to do this for you. You're going to have to parse the JSON into JavaScript Objects then write a few loops to inspect the elements of those objects, probably recursively, to take care of it the way you want. Might make an interesting homework assignment. – UncaAlby Jul 07 '20 at 19:36
  • There’s no such thing as a JSON object. – Terry Jul 07 '20 at 19:38
  • @UncaAlby There is no JSON in this question. You can tell because of the `var obj =`. – Heretic Monkey Jul 07 '20 at 20:19
  • @HereticMonkey The OP modified the question. There was a JSON string in it originally, honest! – UncaAlby Jul 09 '20 at 16:25

2 Answers2

1
function collapseJSON(obj, curStr){
    Object.entries(obj).forEach(([key, value]) => {
    if (typeof value  == "object"){
        collapseJSON(value, key+"_");
    } else{
        console.log(value);
      console.log(typeof value);
        newDict[curStr+"_"+key] = value;
    }
  });
}
collapseJSON(obj);

This is a recursive function that loops over the JSON until it reaches a value that isn't a dictionary. While it looks for a lone value, it adds to the key string. Once it reaches the value, it appends the value to the dictionary under the new key string it made.

NumberC
  • 596
  • 7
  • 17
  • Thank you for replying. Unfortunately this is not going to work for me as you have the number of levels as 2 in the script but as mentioned, i can have N number of levels. Something like below: var obj = { a : { "x": "abc", "y": "def", "z": "ghi" }, b : { "p" : {"abc":"1234", "def" : "2432", "ghi" : {"a" : "1", "b" : "2"}} "q" : "mno", "r" : "pqr" } } – us123133 Jul 07 '20 at 19:51
  • @PankajChakraborty then add the requirement in the question. This works, just make it recursive. Check if the value is object or just string if its object then recursively call itself etc.. – user3647971 Jul 07 '20 at 19:59
  • Well i tried calling it recursively but somehow it's not giving me. Below is code for your reference: var obj = { a : { "x": "abc", "y": "def", "z": "ghi" }, b : { "p" : {"abc":"1234"}}} //as mentioned above processRecords(obj, keyStr); function processRecords(obj, keyStr) { var checkStr = keyStr; for(var key in obj) { if(obj.hasOwnProperty(key) && typeof obj[key] != "string") { checkStr += (checkStr == "") ? key : "_"+key; processRecords(obj[key], checkStr); } else { checkStr += (checkStr == "") ? key : "_"+key; } } } – us123133 Jul 07 '20 at 20:03
  • @check I've fixed my code. This should work for all JSONs now. – NumberC Jul 07 '20 at 20:07
  • Please don't use the word JSON like that. It's not JSON, it's an object. It's only two more letters. JSON is a text format and if I passed actual JSON to that function it would work very differently. – Heretic Monkey Jul 07 '20 at 20:21
  • Yeah, collapseObject maybe better. But good answer. – user3647971 Jul 07 '20 at 20:35
  • This has answer has some flaws tho, didn't work straight out so I smoothed out the edges: function collapseObject(obj, curStr = ""){ var newDict = {}; Object.entries(obj).forEach(([key, value]) => { if (typeof value === "object"){ if(curStr != ""){ var object = collapseObject(value, curStr +"_" +key); }else{ var object = collapseObject(value, key); } newDict = Object.assign(newDict,object); }else{ if(curStr != "") newDict[curStr+"_"+key] = value; else newDict[key] = value; } }); return newDict; } – user3647971 Jul 07 '20 at 20:53
0

This should work as expected:

function collapseObject(obj, currentString = ""){//default value
    var results = {};
    Object.entries(obj).forEach(([key, value]) => {
        if (typeof value  === "object"){
            if(currentString != ""){//dont add underscore if there is no string before it
                var object = collapseObject(value, currentString  +"_" +key);
            }else{
                var object = collapseObject(value, key);
            }
            results = Object.assign(results,object);//merge the objects
        }else{
            if(currentString != "")
                results[currentString +"_"+key] = value;
            else
                results[key] = value;
        }
    });
    return results;
}
console.log(collapseObject(obj));
user3647971
  • 1,069
  • 1
  • 6
  • 13
  • Thanks for replying but it's not going to work for me as I had mentioned there can be N number of levels in the JSON. For Example: var obj = { a : { "x": "abc", "y": "def", "z": "ghi" }, b : { "p" : {"abc":"1234", "def" : "2432", "ghi" : {"a" : "1", "b" : "2"}} "q" : "mno", "r" : "pqr" } } – us123133 Jul 07 '20 at 20:00