简体   繁体   English

使用 lodash 将 JSON 转换为对象数组

[英]Convert JSON to Array of Objects using lodash

I have a JSON object in NoSql database in this format.我在这种格式的 NoSql 数据库中有一个 JSON 对象。 We are getting this data after migrating some records from some other database and these are multi-valued fields.(Basically we are trying to clean the data for further processing).我们在从其他数据库迁移一些记录后获取这些数据,这些是多值字段。(基本上我们正在尝试清理数据以进行进一步处理)。

{
    "BPContName":"aName;bName;cName",
    "BPContEmail":"aEmail;bEmail;cEmail",
    "BPContPWID":"aPWID;bPWID;cPWID"
}

I want to add another key "bpTableDataName" in the same JSON which should have this format and values,我想在同一个 JSON 中添加另一个键“bpTableDataName”,它应该具有这种格式和值,

"bpTableDataName": [
    {
      "name": "aName",
      "email": "aEmail",
      "pwdid": "aPWID"
    },
    {
      "name": "bName",
      "email": "bEmail",
      "pwdid": "bPWID"
    },
    {
      "name": "cName",
      "email": "cEmail",
      "pwdid": "cPWID"
    }
  ],

Is there a way we can achieve this using lodash?有没有办法使用 lodash 来实现这一点?

Try following code -尝试以下代码 -

 o = { "BPContName": "aName;bName;cName", "BPContEmail": "aEmail;bEmail;cEmail", "BPContPWID": "aPWID;bPWID;cPWID" } map = { "BPContName" : "name", "BPContEmail": "email", "BPContPWID": "pwdid" } const result = _.reduce(o, (arr, v, k) => ( v.split(";").forEach((x,i) => _.set(arr, `${i}.${map[k]}`, x)), arr ), []) console.log(result)
 <script src="https://cdn.jsdelivr.net/npm/lodash@4.17.11/lodash.min.js"></script>

You can use split() to split the values into an array.您可以使用split()将值拆分为数组。 Then iterate over the array and create the require json and then push that into results.然后遍历数组并创建 require json,然后将其推送到结果中。

Check this out.看一下这个。

 var data = { "BPContName":"aName;bName;cName", "BPContEmail":"aEmail;bEmail;cEmail", "BPContPWID":"aPWID;bPWID;cPWID" } var names = data.BPContName.split(';'); var emails = data.BPContEmail.split(';'); var pwids = data.BPContPWID.split(';'); var results = []; for(var i = 0 ; i < names.length; i++) { var obj = { name: names[i], email: emails[i], pwdid: pwids[i] } results.push(obj); } console.log(results)

You could reduce the entries returned by Object.entries like this:您可以像这样reduce Object.entries返回的条目:

 let obj = { "BPContName": "aName;bName;cName", "BPContEmail": "aEmail;bEmail;cEmail", "BPContPWID": "aPWID;bPWID;cPWID" } let bpTableDataName = Object.entries(obj).reduce((r, [key, value]) => { let splits = value.split(";"); key = key.replace("BPCont", "").toLowerCase(); splits.forEach((split, i) => (r[i] = r[i] || {})[key] = split) return r; }, []) obj.bpTableDataName = bpTableDataName; console.log(obj)

  • Object.entries returns an array of key-value pair. Object.entries返回一个键值对数组。 Loop through each of them循环遍历它们中的每一个
  • split the each value at ; split每个值;
  • get the key by removing BPCont part and making it lowerCase通过移除拿到钥匙BPCont部分并使其lowerCase
  • Loop through the splits and update specific keys of objects at each index遍历splits并更新每个索引处对象的特定键

Update:更新:

Since you have an extra d in the output's key, you can create a mapping object:由于您在输出的键中有一个额外的d ,您可以创建一个映射对象:

propertyMap = {
  "BPContName": "name",
  "BPContEmail": "email",
  "BPContPWID": "pwdid"
}

And inside the reduce , change the replace code to this:reduce ,将replace代码更改为:

key = propertyMap[key]

Using Object.assign , Object.entries , Array#map and the spread operator make this trivial使用Object.assignObject.entriesArray#map和扩展运算符使这变得微不足道

 const inputdata = { "BPContName":"aName;bName;cName", "BPContEmail":"aEmail;bEmail;cEmail", "BPContPWID":"aPWID;bPWID;cPWID" }; const t1=Object.assign({},...Object.entries(inputdata).map(([k,v])=>({[k]:v.split(';')}))); inputdata.bpTableDataName=t1.BPContName.map((name,i)=>({name,email:t1.BPContEmail[i],pwdid:t1.BPContPWID[i]})); console.log(inputdata);

Of course, it wouldn't be me without a one-liner当然,没有单线就不会是我

 const obj = { "BPContName":"aName;bName;cName", "BPContEmail":"aEmail;bEmail;cEmail", "BPContPWID":"aPWID;bPWID;cPWID" }; // one line to rule them all obj.bpTableDataName=Object.entries(obj).reduce((r,[k,v])=>(v.split(';').forEach((v,i)=>(r[i]=r[i]||{})[{BPContName:'name',BPContEmail:'email',BPContPWID:'pwdid'}[k]]=v),r),[]); // console.log(obj);

You can use lodash's _.flow() to create a function.你可以使用 lodash 的_.flow()来创建一个函数。 Use _.map() with _.overArgs() to create a function that splits the values, format the key, and then converts them to an array of pairs using _.unzip() , for example [['name', 'x'], ['name', 'y']] .使用_.map()_.overArgs()创建一个函数来拆分值,格式化键,然后使用_.unzip()将它们转换为对的数组,例如[['name', 'x'], ['name', 'y']] Transpose the array of arrays with _.unzip() to combine pairs of different properties.使用_.unzip()转置数组数组以组合不同的属性对。 Then use _.map() to iterate, and convert each array of pairs to an object using _.fromPairs() .然后使用_.map()进行迭代,并且使用对每个阵列转换为对象_.fromPairs()

 const { flow, partialRight: pr, map, unzip, overArgs, times, size, constant, split, fromPairs } = _ const keysMap = new Map([['BPContName', 'name'], ['BPContEmail', 'email'], ['BPContPWID', 'pwdid']]) const formatKey = key => keysMap.get(key) const splitVals = pr(split, ';') const fn = flow( pr(map, overArgs( (vals, k) => unzip([vals, times(size(vals), constant(k))]), [splitVals, formatKey]) ), unzip, // transpose pr(map, fromPairs) // convert each pairs array to object ) const data = { "BPContName":"aName;bName;cName", "BPContEmail":"aEmail;bEmail;cEmail", "BPContPWID":"aPWID;bPWID;cPWID" } const results = fn(data) console.log(results)
 <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>

Basically what you need is to zip it.基本上你需要的是zip它。

Snippet:片段:

 let obj = {"BPContName":"aName;bName;cName","BPContEmail":"aEmail;bEmail;cEmail","BPContPWID":"aPWID;bPWID;cPWID"}, res = _.zipWith( ..._.map(obj, v => v.split(';')), (name, email, pwid) => ({name, email, pwid}) ); console.log(res)
 <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>

Note, the sequence of the parameters we have to put such a way, the original object give us values when using Object.values or giving us keys when using Object.keys usually it is alphabetical order.注意,我们必须这样放置参数的顺序,原始对象在使用Object.values时给我们值或在使用Object.keys时给我们键通常是按字母顺序排列的。 But, In case in any env the order is not guranted we can sort it with a sequence of keys as a metadata.但是,如果在任何环境中都不能保证顺序,我们可以使用一系列键作为元数据对其进行排序。

Or else you can explicitly pass the arguments like:否则,您可以显式传递参数,例如:

(obj.BPContName.split(';'), obj.BPContEmail.split(';'), obj.BPContPWID.split(';'))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM