Javascript: 将嵌套对象转换为以值作为路径的对象

Javascript: Convert nested object to object with values as path

这道题不是Fastest way to flatten / un-flatten nested JSON objects的重复题,因为附加值变成键,顺序变化很大,我的对象不是简单的"in a line".

我已经更新了问题描述以使其更清楚。


我有一个嵌套对象,代表控制器映射的多语言路径:

{
  "welcome": {
    "news": {
      "de": "nachrichten",
      "en": "news"
    },
    "de": "willkommen",
    "en": "welcome"
  },
  "applications": {
    "application1": {
      "de": "anwendung1",
      "en": "application1"
    },
    "application2": {
      "features": {
        "de": "funktionen",
        "en": "features"
      },
      "de": "anwendung2",
      "en": "application2"
    },
    "de": "anwendungen",
    "en": "applications"
  }
}

应将其转换为接受路径作为键的易于使用的对象:

{
  "/de/willkommen/": "welcome",
  "/en/welcome/": "welcome",
  "/de/willkommen/nachrichten/": "news",
  "/en/welcome/news/": "news",
  "/de/anwendungen/": "applications",
  "/en/applications/": "applications",
  "/de/anwendungen/anwendung1/": "application1",
  "/en/applications/application1/": "application1",
  "/de/anwendungen/anwendung2/": "application2",
  "/en/applications/application2/": "application2",
  "/de/anwendungen/anwendung2/funktionen/": "features",
  "/en/applications/application2/features/": "features",

}

现在,初始语言特定值("de":"willkommen" 等)构建路径并且是键,初始键是值。但是请看一下,它有点复杂。

我已经构建了一个函数,但它们仅适用于第一级,如“/de/anwendungen/”,不适用于“/de/anwendungen/anwendung1/”及更低级别。

  convertToPath(OldObject, NewObject = {})
  {
    for(let SecondObject in OldObject)
    {
      for(let Key in OldObject[SecondObject])
      {
        NewObject["/" + Key + "/" + OldObject[SecondObject][Key] + "/"] = SecondObject;
      }
    }

    return NewObject;
  }

嗯,你可以通过使用递归遍历来创建你的对象 数据树,像这样:

var data = {
    "welcome": {
        "news": {
            "de": "nachrichten",
            "en": "news"
        },
        "de": "willkommen",
        "en": "welcome"
    },
    "applications": {
        "application1": {
            "de": "anwendung1",
            "en": "application1"
        },
        "application2": {
            "features": {
                "de": "funktionen",
                "en": "features"
            },
            "de": "anwendung2",
            "en": "application2"
        },
        "de": "anwendungen",
        "en": "applications"
    }
};

var langs = ['en', 'de'];

var path_to_controller = function(data, paths, pathsofar){
    paths = paths || {};
    pathsofar = pathsofar || {};
    Object.keys(data).forEach(function(key){
        var newpathsofar;
        if(langs.some(function(lang){ return key === lang; })){
            return;
        }
        newpathsofar = langs.reduce(function(p, lang){
            p[lang] = pathsofar[lang] || '/' + lang + '/';
            p[lang] += data[key][lang] + '/';
            paths[p[lang]] = key;
            return p;
        }, {});
        path_to_controller(data[key], paths, newpathsofar)
    });
    return paths;
};

var paths = path_to_controller(data);
var pre = document.createElement('pre');
pre.innerHTML = JSON.stringify(paths, null, 4);
document.body.appendChild(pre);

您的嵌套对象似乎很难使用,所以我可以理解您想转换成另一种格式。也许您可以安排以更易于使用的格式提供路径数据。

编辑: 推广到任意数量的语言。

和答案 1 的一个小替代方案。虽然我完全同意 'King Mob' 这个结构是有缺陷的并且容易出错。如果您需要名为 "en" 的资源(例如在荷兰语中的意思是 'AND'),请前往 Bantha poodoo's creek。

// target hold the desired output
var target = {};

// languages to distinguish between "a translated resource" and "a resource".
var ls = [ "en", "de" ];
var path = [];
var recurse = function(a,n) {
        // can be made pretty by using ls.
        if (a.hasOwnProperty("de") || a.hasOwnProperty("en"))
    {
        path.push(a);
    }
    var keys = Object.keys(a);
    keys.forEach( 
       function(o) { 
        if (ls.indexOf(o) > -1) {
 var spath = path.reduce( function(pV, cV) { return pV + "/" + cV[o]; }, o);
            target[spath] = n;
        } else {
            recurse(a[o], o);
        }
       }
      );
        // can be made pretty by using ls.
    if (a.hasOwnProperty("de") || a.hasOwnProperty("en"))
    {
        path.pop();
    }
};

// your example data.
var source = {..use your example data.};

// start the recursion
recurse( source );

// output the result
JSON.stringify(target);