3

I have a JSON object in NoSql database in this format. 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,

"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?

8
  • 2
    you can do it in native javascript too Commented Mar 19, 2019 at 11:54
  • 1
    Welcome to Stack Overflow! Please take the tour (you get a badge!) and read through the help center, in particular How do I ask a good question? Your best bet here is to do your research, search for related topics on SO, and give it a go. If you get stuck and can't get unstuck after doing more research and searching, post a minimal reproducible example of your attempt and say specifically where you're stuck. People will be glad to help. Note: The fact it starts out as JSON is irrelevant. By the time you've parsed it, it's just an object, not a "JSON object." Commented Mar 19, 2019 at 11:56
  • @JaromandaX I am new to JavaScript actually. Can you please tell me how? Commented Mar 19, 2019 at 12:01
  • You have PWID in the original object but pwdid with an extra d in the output. Is that a spelling error? Commented Mar 19, 2019 at 12:14
  • @KirtiJha I have updated my answer to suit your use case. Commented Mar 19, 2019 at 12:19

6 Answers 6

1

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/[email protected]/lodash.min.js"></script>

Sign up to request clarification or add additional context in comments.

4 Comments

ReferenceError: _ is not defined ... fail
You must import lodash first : const _ = require('lodash')
ReferenceError : require is not defined ... still fail - don't make a runnable snippet that doesn't run - it doesn't look good
oh that's no good at all, you're basing the key on the data!! I think aName;bName etc are example place holders for such names as Adam, Brian, Charlie etc
0

You can use split() to split the values into an array. Then iterate over the array and create the require json and then push that into results.

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)

Comments

0

You could reduce the entries returned by Object.entries like this:

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. Loop through each of them
  • split the each value at ;
  • get the key by removing BPCont part and making it lowerCase
  • Loop through the splits and update specific keys of objects at each index

Update:

Since you have an extra d in the output's key, you can create a mapping object:

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

And inside the reduce, change the replace code to this:

key = propertyMap[key]

1 Comment

I was going along your lines too, until I saw that :p
0

Using Object.assign, Object.entries, Array#map and the spread operator make this trivial

    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);

Comments

0

Basically what you need is to zip it.

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. 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(';'))

Comments

0

You can use lodash's _.flow() to create a function. 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']]. Transpose the array of arrays with _.unzip() to combine pairs of different properties. Then use _.map() to iterate, and convert each array of pairs to an object using _.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>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.