0

I am trying to add '_x' to every object key and '_y' to every object value. This is the code:

var data = {
  "glossary": {
    "title": "example glossary",
    "GlossDiv": {
      "title": "S",
      "GlossList": {
        "GlossEntry": {
          "ID": "SGML",
          "SortAs": "SGML",
          "GlossTerm": "Standard Generalized Markup Language",
          "Acronym": "SGML",
          "Abbrev": "ISO 8879:1986",
          "GlossDef": {
            "para": "A meta-markup language, used to create markup languages such as DocBook.",
            "GlossSeeAlso": "GMLXML"
          },
          "GlossSee": "markup"
        }
      }
    }
  }
}

function treee(data) {
  Object.keys(data).map( function (key) {
    if(Object.keys(data[key]).length == 0){
      data[key] =  {[key + "_x"]: data[key] + "_y"};
    }
    else{
      data[key] =  { [key + "_x"]: treee(data[key]) };
    }
  });
}

It is not working and I don't know why. Can you please tell what is wrong?

Majid Fouladpour
  • 29,356
  • 21
  • 76
  • 127
theCode
  • 1,997
  • 4
  • 18
  • 28
  • 1
    [JSON](http://json.org/) is a string. if you don't have a string, then it's not JSON. just something different, like an object, or an array. – Nina Scholz Dec 06 '16 at 12:52
  • JSON.parse... I don't see that anywhere – zerohero Dec 06 '16 at 12:53
  • please **change the title** to one which describes the issue. – vsync Dec 06 '16 at 12:53
  • @zerohero You only need `JSON.parse()` when you have JSON. – Reinstate Monica Cellio Dec 06 '16 at 12:54
  • 2
    Why the downvotes? This is a legitimate question; it just happens the OP mentions JSON, where he means Object (and that is clear from the code) – Majid Fouladpour Dec 06 '16 at 12:57
  • The downvotes are probably coming because the problem is due to making some very wrong assumptions about what types of object in JavaScript come with a `length` property which would be trivial to detect with some basic debugging (i.e. by looking at what the values being tested in the `if` statements actually are). – Quentin Dec 06 '16 at 13:00
  • The other reason for the downvotes is that "it is not working and I don't know why" is a very bad problem statement. – Quentin Dec 06 '16 at 13:01
  • The third likely reason for downvotes is that there is no [mcve]. The `treee` function never gets called. The output never gets examined. – Quentin Dec 06 '16 at 13:02
  • @Archer That's because the variable data contains JSON.... – zerohero Dec 07 '16 at 06:02
  • @zerohero There is no JSON there - it's an object. Just drop it. – Reinstate Monica Cellio Dec 07 '16 at 07:22
  • @Archer won't dropping the object make his code error out? I'm confused. – zerohero Dec 07 '16 at 07:48
  • @zerohero - please post what you think is JSON from the code posted above. I'll explain to you why you're wrong so you don't do the same thing again in the future :) – Reinstate Monica Cellio Dec 07 '16 at 07:50
  • @Archer the entire data variable looks (and verifies) as JSON, how can it be used as an object where I can go data.glossary.GlossList.GlossEntry.ID? – zerohero Dec 07 '16 at 07:56
  • 1
    @zerohero JSON is a string. It is a string representation of an object. Read more here... http://stackoverflow.com/questions/383692/what-is-json-and-why-would-i-use-it – Reinstate Monica Cellio Dec 07 '16 at 08:46

2 Answers2

2

Basically you need the new key instead of the old one and delete the actual one.

Another part is to change an inner object, if necessaray.

function treee(data) {
    Object.keys(data).map(function (key) {
        if (data[key] && typeof data[key] === 'object') {
            treee(data[key]);
        }
        data[key + '_x'] = typeof data[key] === 'string' ? data[key] + '_y' : data[key];
        delete data[key];
    });
}

var data = { glossary: { title: "example glossary", GlossDiv: { title: "S", GlossList: { GlossEntry: { ID: "SGML", SortAs: "SGML", GlossTerm: "Standard Generalized Markup Language", Acronym: "SGML", Abbrev: "ISO 8879:1986", GlossDef: { para: "A meta-markup language, used to create markup languages such as DocBook.", GlossSeeAlso: "GMLXML" }, GlossSee: "markup" } } } } };

treee(data);
console.log(data);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
2

This is easier to do if you convert the object to JSON, then use string replacements:

var data = { "glossary": { "title": "example glossary", "GlossDiv": { "title": "S", "GlossList": { "GlossEntry": { "ID": "SGML", "SortAs": "SGML", "GlossTerm": "Standard Generalized Markup Language", "Acronym": "SGML", "Abbrev": "ISO 8879:1986", "GlossDef": { "para": "A meta-markup language, used to create markup languages such as DocBook.", "GlossSeeAlso": "GMLXML" }, "GlossSee": "markup" } } } } }

var jsonString = JSON.stringify(data),
    replacedValues = jsonString
        .replace(/([\w.])"/g, '$1_y"') // Add _y to all strings in there.
        .replace(/_y":/g, '_x":')      // Replace _y with _x for all keys.
    newData = JSON.parse(replacedValues);

console.log(newData);

Another option would be to use a regex to replace the keys, then use a reviver function to modify the values, when parsing the JSON:

var data = { "glossary": { "title": "example glossary", "GlossDiv": { "title": "S", "GlossList": { "GlossEntry": { "ID": "SGML", "SortAs": "SGML", "GlossTerm": "Standard Generalized Markup Language", "Acronym": "SGML", "Abbrev": "ISO 8879:1986", "GlossDef": { "para": "A meta-markup language, used to create markup languages such as DocBook.", "GlossSeeAlso": "GMLXML" }, "GlossSee": "markup" } } } } }

var jsonString = JSON.stringify(data)
        .replace(/":/g, '_x":');    // Add _x to all keys.

var newData = JSON.parse(jsonString, function(key, val){
    if(typeof val === 'string')     // For every value, if the value is a string
        return val + '_y';          // Add `_y`
    return val;                     // Otherwise, just return the value.
});

console.log(newData);
Cerbrus
  • 70,800
  • 18
  • 132
  • 147