将源 JSON 字符串合并到具有相似键但 javascript 结构不同的目标

Merge source JSON string to target with similar keys but different structure in javascript

提问人:raj.rajpurohit6 提问时间:10/28/2020 最后编辑:Eleraj.rajpurohit6 更新时间:2/25/2022 访问量:234

问:

我有两个JSON字符串,如下所示:

source = [
  {
    "name": "test1",
    "values": ["User Support"],
    "enabled": false
  },
  {
    "name": "test2",
    "values": ["M"],
    "enabled": true
  },
  {
    "name": "test3",
    "values": ["CA"],
    "enabled": false
  }
]

target = [{
    "name": "test1",
    "values": [{
        "value": "User Support",
        "selected": false
      },
      {
        "value": "Engineering",
        "selected": false
      },
      {
        "value": "Implementation",
        "selected": false
      }
    ],
    "enabled": false
  },
  {
    "name": "test2",
    "values": [{
        "value": "M",
        "selected": false
      },
      {
        "value": "F",
        "selected": false
      }
    ],
    "notEnabled": false
  },
  {
    "name": "test3",
    "values": [{
        "value": "CA",
        "selected": false
      },
      {
        "value": "EN",
        "selected": false
      }
    ],
    "enabled": false
  }
]

我想将这两个JSON字符串合并到目标中,结果应如下所示:

target = [{
    "name": "test1",
    "values": [{
        "value": "User Support",
        "selected": true
      },
      {
        "value": "Engineering",
        "selected": false
      },
      {
        "value": "Implementation",
        "selected": false
      }
    ],
    "enabled": false
  },
  {
    "name": "test2",
    "values": [{
        "value": "M",
        "selected": true
      },
      {
        "value": "F",
        "selected": false
      }
    ],
    "enabled": true
  },
  {
    "name": "test3",
    "values": [{
        "value": "CA",
        "selected": true
      },
      {
        "value": "EN",
        "selected": false
      }
    ],
    "enabled": false
  }
]

所以,我试图做的是在目标字符串中搜索名称为 test1、test2......然后,如果在源 JSON 字符串中找到该值,则将所选字段设置为 true。enabled 字段也是如此。

我想到的第一件事是为每个循环使用嵌套并检查键。 在 Javascript 中还有其他更好的方法可以做到这一点吗?

请注意,目标字符串中可能存在其他键,但除非它们存在于源字符串中,否则我们不会理会它们。

JavaScript 数组 JSON 字符串

评论

0赞 ikwillem 10/28/2020
我不知道这是否是你所说的“更好的 eay”的意思,但也许这适合你:stackoverflow.com/questions/4720494/......
1赞 Yoshi 10/28/2020
你试过什么吗?这看起来并不太复杂。只需遍历您的源并在目标中找到适当的位置。
1赞 Bergi 10/28/2020
不,鉴于您的 结构 ,您需要使用循环而不是能够查找。嵌套循环是完全可以的,只有当你的源有非常大的数组(而不仅仅是其中的单个值)时,为每个目标构建一个是有意义的。此外,如果两个数组始终以相同的顺序排序,则可以利用这一点。valuesvaluesMap
0赞 raj.rajpurohit6 10/28/2020
是的,我尝试过嵌套循环,它看起来像这样:for(let i = 0; i < source.length; ++i) for(let j = 0; j < target.length; ++j){ if(_.isEqual(source[i]["name"], target[j]["name"])){ target[j]["enabled"] = source[i]["enabled"]; for(let k = 0; k < target[j]["values"].length; ++k) for(let l = 0; l < source[i]["values"].length; ++l) if(_.isEqual(target[j]["values"][k]["value"],source[i]["values"][l])) target[j]["values"][k]["selected"] = true; } }

答:

0赞 A1exandr Belan 10/28/2021 #1

如果你不介意 lodash:

const _ = require('lodash');

const sourceJSON = '[{"name":"test1","values":["User Support"],"enabled":false},{"name":"test2","values":["M"],"enabled":true},{"name":"test3","values":["CA"],"enabled":false}]';
const targetJSON = '[{"name":"test1","values":[{"value":"User Support","selected":false}, {"value":"Engineering","selected":false},{"value":"Implementation","selected":false}],"enabled":false},{"name":"test2","values":[{"value":"M","selected":false},  {"value":"F","selected":false} ],"notEnabled":false},{ "name":"test3","values": [{"value":"CA","selected":false},{"value":"EN","selected":false}],"enabled":false}]';

const source = JSON.parse(sourceJSON);
const target = JSON.parse(targetJSON);

const sourceNormalized = source.map((obj) => (
  { ...obj, values: [{value: obj.values[0], selected: true}] }
));

const merged = _.defaultsDeep(sourceNormalized, target);
console.dir(merged, {depth: null});
// [ { name: 'test1',
//     values: [
//       { value: 'User Support', selected: true },
//       { value: 'Engineering', selected: false },
//       { value: 'Implementation', selected: false }
//     ],
//     enabled: false
//   },
//   { name: 'test2',
//     values: [ 
//       { value: 'M', selected: true }, 
//       { value: 'F', selected: false } 
//     ],
//     enabled: true,
//     notEnabled: false
//   },
//   { name: 'test3',
//     values: [
//       { value: 'CA', selected: true },
//       { value: 'EN', selected: false }
//     ],
//     enabled: false} ] 

result = JSON.stringify(merged);
0赞 jsN00b 1/1/2022 #2

之前使用 lodash 的答案是一个非常好的方法。如果你遇到像我这样的情况(被困在一个代码库上,其中包,包括 lodash,很难获得批准使用),这里有一个使用 Vanilla-javascript (+ JSON.stringify) 的方法:

const delta = [{
    "name": "test1",
    "values": ["User Support"],
    "enabled": false
  },
  {
    "name": "test2",
    "values": ["M"],
    "enabled": true
  },
  {
    "name": "test3",
    "values": ["CA"],
    "enabled": false
  }
];

const orig = [{
    "name": "test1",
    "values": [{
        "value": "User Support",
        "selected": false
      },
      {
        "value": "Engineering",
        "selected": false
      },
      {
        "value": "Implementation",
        "selected": false
      }
    ],
    "enabled": false
  },
  {
    "name": "test2",
    "values": [{
        "value": "M",
        "selected": false
      },
      {
        "value": "F",
        "selected": false
      }
    ],
    "notEnabled": false
  },
  {
    "name": "test3",
    "values": [{
        "value": "CA",
        "selected": false
      },
      {
        "value": "EN",
        "selected": false
      }
    ],
    "enabled": false
  }
];

const getTargetJSON = (delta, orig, debug = true) => { // method signature
  const deltaMapper = delta.reduce((f, i) => ({
    ...f,
    [i.name]: {
      values: [...i.values],
      enabled: i.enabled
    }
  }), {});
  const target = orig.map(itm => ({
    ...itm,
    values: itm.values.map(it2 => ({
      ...it2,
      selected: deltaMapper[itm.name].values.includes(it2.value) || false
    })),
    enabled: deltaMapper[itm.name].enabled || false
  }));

  debug && console.log('Merged Target:\n', target);
  return JSON.stringify(target);
};

getTargetJSON(delta, orig); // method call

方法/解释

我们将问题分解为更小的问题。

  • 首先,使用源(在 代码片段)
  • 接下来,遍历目标(名为“orig”)并利用 map(在上面创建)以确定值是否被“选中”,并且 item 为“已启用”。