【问题标题】:Merge source JSON string to target with similar keys but different structure in javascript将源 JSON 字符串合并到具有相似键但在 javascript 中具有不同结构的目标
【发布时间】:2021-02-10 12:21:23
【问题描述】:

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

来源 =

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

目标 =

[
{"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 字符串合并到目标中,结果应该如下所示:

目标 =

[
{"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。启用字段也是如此。

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

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

【问题讨论】:

  • 我不知道这是否是您所说的“更好的 eay”的意思,但也许这对您来说很合适:stackoverflow.com/questions/4720494/…
  • 你有没有尝试过?这看起来并不太复杂。只需遍历您的源并在目标中找到适当的位置。
  • 不,鉴于您的values 结构,您需要使用循环而不是查找。嵌套循环完全没问题,只有当您的源有非常大的 values 数组(不仅仅是其中的单个值)时,为每个目标构建一个 Map 才有意义。此外,如果两个数组始终按相同顺序排序,您可以利用这一点。
  • 是的,我尝试过嵌套循环,它看起来像这样: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; } }

标签: javascript arrays json string


【解决方案1】:

previous answer 使用 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

方法/解释

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

  • 首先,使用源生成地图(在 代码-sn-p)
  • 接下来,遍历目标(名为“orig”)并利用 映射(在上面创建)以确定值是否被“选择”和 项目已“启用”。

【讨论】:

    【解决方案2】:

    如果你不介意 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);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-05-20
      • 1970-01-01
      • 2020-07-28
      • 1970-01-01
      • 1970-01-01
      • 2020-12-18
      • 1970-01-01
      • 2021-12-31
      相关资源
      最近更新 更多