JavaScript从另一个JSON对象填充一个JSON对象中的缺失键

时间:2017-08-23 12:44:48

标签: javascript json

我有一个JSON对象 object1 需要从 object2 填充缺少的字段 - 不应替换现有字段。

我曾经使用过这个功能:

function fillObject(from, to) {
    for (var key in from) {
        if (from.hasOwnProperty(key)) {
            if (Object.prototype.toString.call(from[key]) === '[object Object]') {
                if (!to.hasOwnProperty(key)) {
                    to[key] = {};
                }
                fillObject(from[key], to[key]);
            }
            else if (!to.hasOwnProperty(key)) {
                to[key] = from[key];
            }
        }
    }
}

它始终有效,两个对象都具有相同的结构。现在 object1 中的实际上可以出现在结构中的任何位置。示例 object1 object2 (结构可能看起来很有趣,因为我删除了所有不必要的密钥)。< / p>

var object1 = [
    {
        "position": 1,
        "items": [
            { 
                "position": 1, "itemId": 431
            },
            {
                "position": 2, "itemId": 1162, "title": "Overwritten title"
            }
        ]
    },
    {
        "position": 2,
        "groups": [
            {
                "position": 1
                "items": [
                    {
                        "position": 1, "itemId": 452, "title": "New title"
                    },
                    {
                        "position": 2, "itemId": 1388
                    },
                    {
                        "position": 3, "itemId": 1942
                    }
                ]
            },
            { 
                "position": 2, "itemId": 1942 
            },
            {
                "position": 3,
                "items": [
                    {
                        "position": 1, "itemId": 431
                    },
                    {
                        "position": 2, "itemId": 2000
                    },
                    {
                        "position": 3, "itemId": 452
                    }
                ]
            }
        ]
    },
    {
        "position": 3, "itemId": 1388
    },
    {
        "position": 4, "itemId": 2000, "title": "Extra title"
    }
];

var object2 [
    { "itemId": 431, "title": "Title 1" },
    { "itemId": 452, "title": "Title 2" },
    { "itemId": 1162, "title": "Title 3" },
    { "itemId": 1388, "title": "Title 4" },
    { "itemId": 1942, "title": "Title 5" },
    { "itemId": 2000 }
];

这就是我想要的结果:

var object1 = [
    {
        "position": 1,
        "items": [
            {
                "position": 1, "itemId": 431, "title": "Title 1"
            },
            {
                "position": 2, "itemId": 1162, "title": "Overwritten title"
            }
        ]
    },
    {
        "position": 2,
        "groups": [
            {
                "position": 1,
                "items": [
                    {
                        "position": 1, "itemId": 452, "title": "New title"
                    },
                    {
                        "position": 2, "itemId": 1388, "title": "Title 4"
                    },
                    {
                        "position": 3, "itemId": 1942, "title": "Title 5"
                    }
                ]
            },
            {
                "position": 2, "itemId": 1942, "title": "Title 5"
            },
            {
                "position": 3,
                "items": [
                    {
                        "position": 1, "itemId": 431, "title": "Title 1"
                    },
                    {
                        "position": 2, "itemId": 2000
                    },
                    {
                        "position": 3, "itemId": 452, "title": "Title 2"
                    },
                ]
            }
        ]
    },
    {
        "position": 3, "itemId": 1388, "title": "Title 4"
    },
    {
        "position": 4, "itemId": 2000, "title": "Extra title"
    }
];

提前感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

如果您可以通过属性识别对象(例如itemId),则可以执行以下操作

  • 将您的任务拆分为小子任务:复制缺失属性,遍历对象结构,查找对象的相应来源
  • 将这些小块功能实现为功能并一起使用。

&#13;
&#13;
const defaults = (target, src) => Object.keys(src)
  .forEach(key => key in target || (target[key] = src[key]))

const traverse = fn => traversable => {
  fn(traversable)
  
  const nested = Array.isArray(traversable) ? traversable : Object.values(traversable)  
  
  nested.filter(value => typeof value === 'object')
        .forEach(traverse(fn))
}

const fillById = id => sources => {
  const mapping = new Map(sources.map(item => [item[id], item]))
  
  return obj => {
    const src = mapping.get(obj.itemId)
    
    src && defaults(obj, src)
  }
}

var object1 = [
    {
        "position": 1,
        "items": [
            { 
                "position": 1, "itemId": 431
            },
            {
                "position": 2, "itemId": 1162, "title": "Overwritten title"
            }
        ]
    },
    {
        "position": 2,
        "groups": [
            {
                "position": 1,
                "items": [
                    {
                        "position": 1, "itemId": 452, "title": "New title"
                    },
                    {
                        "position": 2, "itemId": 1388
                    },
                    {
                        "position": 3, "itemId": 1942
                    }
                ]
            },
            { 
                "position": 2, "itemId": 1942 
            },
            {
                "position": 3,
                "items": [
                    {
                        "position": 1, "itemId": 431
                    },
                    {
                        "position": 2, "itemId": 2000
                    },
                    {
                        "position": 3, "itemId": 452
                    }
                ]
            }
        ]
    },
    {
        "position": 3, "itemId": 1388
    },
    {
        "position": 4, "itemId": 2000, "title": "Extra title"
    }
];

var object2 =  [
    { "itemId": 431, "title": "Title 1" },
    { "itemId": 452, "title": "Title 2" },
    { "itemId": 1162, "title": "Title 3" },
    { "itemId": 1388, "title": "Title 4" },
    { "itemId": 1942, "title": "Title 5" },
    { "itemId": 2000 }
];



traverse(fillById('itemId')(object2))(object1)

console.log(object1)
&#13;
&#13;
&#13;