将JavaScript字典转换为JSON格式

Turn javascript dictionary into JSON format

本文关键字:JSON 格式 转换 JavaScript 字典      更新时间:2023-09-26

我有一个javascript字典:

{
  "a": {
      "b": {
          "c": null,
          "d": null
           }
       }
}

如何将其转换为可以指定名称和子属性的 JSON 对象?有什么优雅的方法可以做到这一点吗?JSON 对象可以是:

{
    name:"a"
    children: [{
      name:"b",
      children: [{
          name:"c",
          children: null
           },{
          name:"d",
          children: null}]
       }]
  }

您可以创建一个递归函数来生成输出:

var x = {
    "a": {
        "b": {
            "c": null,
            "d": null
        }
    }
};
function generate(item, key) {
    var result = {
        name: key,
        children: []
    };
    for (var _ in item)
        result.children.push(generate(item[_], _))
    if (result.children.length == 0)
        result.children = null;
    return (key == undefined) ? result.children : result;
}
console.log(JSON.stringify(generate(x), null, 1));

输出:

[
 {
  "name": "a",
  "children": [
   {
    "name": "b",
    "children": [
     {
      "name": "c",
      "children": null
     },
     {
      "name": "d",
      "children": null
     }
    ]
   }
  ]
 }
]

上面的 generate 函数返回列表而不是字典,因为在根级别可能有多个名称。但是如果我们确定根名称中只有一个名称,我们可以像这样生成 json:

console.log(JSON.stringify(generate(x)[0], null, 1));

这是我的解决方案。它类似于JuniorCompressor的。

function generate(obj) {
  // Return primitives as-is
  if (!(obj instanceof Object)) return obj;
  // Loop through object properties and generate array
  var result = [];
  for (var key in obj) {
    result.push({
      name:     key,
      children: generate(obj[key])
    });
  }
  // Return resulting array
  return result;
}

如前所述,生成的对象实际上将是一个数组(如果原始对象中有多个根级属性)。如果您确实需要结果对象是仅具有属性名称和值的对象,则应访问结果数组的第一个元素,如下所示:

generate(obj)[0]

解决方案

你需要一个递归函数,它为子函数调用自己。请注意,在您的示例中,只有一个顶级子级 (a)。相反,我使用这样的假设,即顶级"名称"是指实际对象本身的名称。如果你想从一个名为 'obj' 的对象获得与你演示的结果完全相同的结果,请运行 toJSON(obj).children[0]。对于整体功能,请尝试如下操作:

function toJSON(obj, name) {
    var subTree = {
        name: name,
        children: []
    };
    if (obj !== null && Object.keys(obj).length >= 1) {
        for (var child in obj) {
            subTree.children.push(toJSON(obj[child], child));
        }
    } else {
        subTree.children = null;
    }
    return subTree;
}

toJSON(obj).children[0]的结果:

{
    "name": "a",
    "children": [{
        "name": "b",
        "children": [{
            "name": "c",
            "children": null
        },{
            "name": "d",
            "children": null
        }]
    }]
}

结果 to JSON(obj, 'obj'):

{
    "name": "obj",
    "children": [{
        "name": "a",
        "children": [{
            "name": "b",
            "children": [{
                "name": "c",
                "children":null
            },
            {
                "name": "d",
                "children": null
            }]
        }]
    }]
}

以下是逐行说明:

  1. 声明函数,该函数需要两个参数:对象及其名称。但是,如果你打算使用toJSON(obj).children[0],请不要打扰第二个参数。它不会影响结果。
  2. 声明结果,一个对象,其中包含有关当前级别和对象中所有级别的信息。如果将对象视为树,则此结果包含有关当前分支及其所有分支的信息。
  3. 声明属性"name",包含当前级别的对象的名称/键。调用函数时,需要包含 name 作为第二个参数,因为无法动态查找变量的名称。它们按值传递到函数中。但是,如上所述,如果您正在寻找与示例中完全相同的结果,您将使用 toJSON(obj).children[0],而不是 toJSON(obj, 'obj'),然后不需要打扰第二个参数。
  4. 声明子数组,将在下面填充
  5. 终止从第 2 行开始的声明
  6. 检查对象是否不为 null,以及它是否有子对象,使用 Object 内置对象的便捷方法,如果是,则运行第 7、8 和 9 行
  7. 遍历对象的子项,为每个子项运行第 8 行
  8. 递归地为每个子级运行 toJSON() 函数,以获取它的子树。因为孩子们不能动态地找出自己的名字,所以它也会传递这些名字。
  9. 终止从7号线开始的for环路
  10. 如果没有孩子,请运行11号线。仅当第 7、8 和 9 行未运行时,才会运行此操作。
  11. 将子项设置为 null(仅在没有子项时才运行,由第 6 行检查)
  12. 终止从第 10 行开始的 else
  13. 返回
  14. 当前子树,如果函数以递归方式调用函数,则返回给您,如果您自己调用它,则返回给您
  15. 终止函数

有关先前版本的信息,预编辑

原始函数只使用一个参数,而上面的函数有另一个参数用于"name"。这是因为原版试图找出同一关卡中每个关卡的名称,后来我意识到这在 Javascript 中是不可能的。基本上,原始版本不起作用,必须添加一个额外的参数才能使其正常工作。不过,为了记录起见,这是原始功能:

// THIS FUNCTION DOESN'T WORK. IT'S HERE ONLY FOR HISTORICAL ACCURACY:
function toJSON(obj) {
    var subTree = {
        name: obj.constructor.name,       // This should get the object key
        children: []
    };
    if (Object.keys(obj).length >= 1) {   // If there is at least one child
        for (var child in obj) {
            subTree.children.push(toJSON(obj[child]));
        }
    } else {
        subTree.children = null;
    }
    return subTree;
}