Javascript 递归地遍历嵌套对象以进行深度复制,并从单独的数据源应用默认值

Javascript 递归地遍历嵌套对象以进行深度复制,并从单独的数据源应用默认值,javascript,object,Javascript,Object,好吧,这一个可能是个傻瓜。我正在努力,但不知道是否有一个优雅的方式来处理这个问题 我有一个资产对象,每个对象都有一些属性,以及两个可能对象中的一些子资产:资产和特征 我还有一个平面对象,其中存储了每种类型的资产的默认值 我希望遍历对象,从ID检测我正在查看的资产类型,从flat defaults对象加载属性,覆盖嵌套对象中存在的任何属性,并返回一个新的嵌套对象,该对象具有所有默认值,但也使用原始嵌套对象中存在的任何内容进行更新 例如,嵌套对象: { "id": "

好吧,这一个可能是个傻瓜。我正在努力,但不知道是否有一个优雅的方式来处理这个问题

我有一个资产对象,每个对象都有一些属性,以及两个可能对象中的一些子资产:资产和特征

我还有一个平面对象,其中存储了每种类型的资产的默认值

我希望遍历对象,从ID检测我正在查看的资产类型,从flat defaults对象加载属性,覆盖嵌套对象中存在的任何属性,并返回一个新的嵌套对象,该对象具有所有默认值,但也使用原始嵌套对象中存在的任何内容进行更新

例如,嵌套对象:

{
  "id": "Bohemian Rhapsody",
  "version": "0.10.1.5",
  "manifest": "6s43qhuy53as980u08647ugp864q867-08d4svbn9uh54xc8vu",
  "slug": "DarkShiftingBolt",
  "visibility": "friends",
  "locked": true,
  "values": {"value0":2},
  "assets": [
    {
      "id": "I see",
      "assets": [
        {
          "id": "a little",
          "name": "Queen",
          "values": {
            "value1": 1,
            "value2": 3,
            "value3": 2
          },
          "characteristics": [
            {
              "id": "silhouetto",
              "assets": [
                {
                  "id": "of a man",
                  "values": {
                    "value4": 3,
                    "value5": 1
                  },
                  "assets": [
                    {"id": "Scaramouche"}
                  ]
                }
              ]
            }
          ],
          "assets": [
            {"id": "Scaramouche"}
          ]
        },
        {
          "id": "will you",
          "name": "Freddy",
          "values": {
            "value1": 1,
            "value2": 0,
            "value3": 3
          },
          "assets": [
            {
              "id": "do the",
              "assets": [
                {"id": "fandango"}
              ]
            }
          ]
        }
      ]
    }
  ]
}
平面默认对象:

{
  "Bohemian Rhapsody": {
    "visibility": "hidden",
    "locked": false,
    "values": {"value0":1},
  },
  "I see": {
    "cost": 4
  },
  "a little": {
    "values": {
      "value2": 1,
      "value4": 5
    },
  },
  "silhouetto": {
    "cost": 1
  },
  "of a man": {
    "genre": "opera"
  },
  "Scaramouche": {
    "rank": 3
  },
  "will you": {
    "values": {
      "value4": 0
    },
  },
  "do the": {
    "signature": [[4,4],[2,4],[6,8]]
  },
  "fandango": {
    "records": ["thunderbolts","lightning"]
  }

}
所需的输出对象:

{
  "id": "Bohemian Rhapsody",
  "version": "0.10.1.5",
  "manifest": "6s43qhuy53as980u08647ugp864q867-08d4svbn9uh54xc8vu",
  "slug": "DarkShiftingBolt",
  "visibility": "hidden",
  "locked": false,
  "values": {"value0":1},
  "assets": [
    {
      "id": "I see",
      "cost": 4,
      "assets": [
        {
          "id": "a little",
          "name": "Queen",
          "values": {
            "value1": 1,
            "value2": 1,
            "value3": 2,
            "value4": 5
          },
          "characteristics": [
            {
              "id": "silhouetto",
              "assets": [
                {
                  "id": "of a man",
                  "genre": "opera",
                  "values": {
                    "value4": 3,
                    "value5": 1
                  },
                  "assets": [
                    {
                      "id": "Scaramouche",
                      "rank": 3
                    }
                  ]
                }
              ]
            }
          ],
          "assets": [
            {
              "id": "Scaramouche",
              "rank": 3
            }
          ]
        },
        {
          "id": "will you",
          "name": "Freddy",
          "values": {
            "value1": 1,
            "value2": 0,
            "value3": 3,
            "value4": 0
          },
          "assets": [
            {
              "id": "do the",
              "signature": [[4,4],[2,4],[6,8]],
              "assets": [
                {
                  "id": "fandango",
                  "records": ["thunderbolts","lightning"]
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}

我尝试的是一个object.keys递归函数,它根据找到的属性构建一个新对象。我很想知道是否有更聪明的方法来解决这个问题。

多亏了@rayhatfield

import * as merge from 'deepmerge';

    this.manifest = (manifestData  as  any).default;
    this.list = (listData  as  any).default;
    this.list = this.assetIterate(this.list);

  assetIterate(asset){
    let id = asset.id;
    let type = this.manifest.asset_catalog[id].type;
    let newAsset = merge.all([this.manifest.asset_taxonomy[type],this.manifest.asset_catalog[id],asset])
    Object.keys(asset).forEach((key) => {
      if(key === "characteristics" || key === "assets"){
        newAsset[key] = [...asset[key]] 
        newAsset[key].forEach((asset,index) => {
          newAsset[key][index] = this.assetIterate(asset);
        });
      }
    });
    asset = {...newAsset}
    return asset
  }

似乎适用于所有情况,除了子数组需要替换索引而不是串联索引的情况,但我可以在特殊情况下,当我实际制作其中一个索引时。

如果您不想自己动手,可以使用现成的解决方案,如。@rayhatfield谢谢,这几乎适用于所有情况(还有一些重复的垃圾)