-1

I have following JSON objects in one of my parser programs written years ago.

{"Date":"19/02/16","Narration":"NEFT DR-BARB0PIMPAL-Govt. NE","Chq":{"/Ref":{"No":{"":"N050160130709970"}}},"Value Dt":"19/02/16","Withdrawal Amt":{"":"8,000.00"},"Deposit Amt":{"":""},"Closing Balance":"24,114.95"}

{"Date":"","Narration":"TBANK, MUM-N050160130709970","Chq":{"/Ref":{"No":{"":""}}},"Value Dt":"","Withdrawal Amt":{"":""},"Deposit Amt":{"":""},"Closing Balance":""}

Basically, the above entry should have been a single record. However, due to line wrapping the parser treating them as a new record.

I tried mapping the objects by converting them into an array. However, then the map resulted as the following JSON object.

{"Date":"19/02/16"}{"Date":""},{"Narration":"NEFT DR-BARB0PIMPAL-Govt. NE"}{"Narration":"TBANK, MUM-N050160130709970"},{"Chq":{"/Ref":{"No":{"":"N050160130709970"}}}}{"Chq":{"/Ref":{"No":{"":""}}}},{"Value Dt":"19/02/16"}{"Value Dt":""},{"Withdrawal Amt":{"":"8,000.00"}}{"Withdrawal Amt":{"":""}},{"Deposit Amt":{"":""}}{"Deposit Amt":{"":""}},{"Closing Balance":"24,114.95"}{"Closing Balance":""}

What I need to have is a merged/combined array OR object with main keys remain intact and values join/append to the first element (second object to be discarded thereafter.)

For example.

{"Date":"19/02/16","Narration":"NEFT DR-BARB0PIMPAL-Govt.NETBANK","Chq":{"/Ref":{"No":{"":"N050160130709970MUM-N050160130709970"}}},"Value Dt":"19/02/16","Withdrawal Amt":{"":"8,000.00"},"Deposit Amt":{"":""},"Closing Balance":"24,114.95"}

Can you guys suggest if I can directly merge/combine the source JSON Object or merge the arrays with above effects?

WebDevBooster
  • 14,674
  • 9
  • 66
  • 70
NBaua
  • 583
  • 4
  • 16
  • 33
  • 1
    Read about jQuery extend (https://api.jquery.com/jquery.extend/), but I think it doesn't fit your requirements because it keeps the value of the "main" object, but not appends values. Perhaps you must implement your own method similar at this post (https://stackoverflow.com/a/33850667/803195) – Marc Feb 12 '18 at 09:55
  • The challenge appears to be keeping the order of records intact when processing such that consecutive parts of the single actual record that had been split in parsing are kept together. If you have the lexicalized JSON data, augment that into a JSON array of records and process it thereafter with a convenient tool. – collapsar Feb 12 '18 at 09:56
  • @Marc , I already tried working with mapping/custom function, but need cleaner approach, BTW your SO post does not solve my problem either, you should have validated my scenario before suggesting (and down-voting). – NBaua Feb 13 '18 at 06:23
  • @nbaua I haven't downvoted your post, I've written my comment in order to help you to find the proper solution. I knew that it wasn't a solution, thereby I hadn't post as answer. – Marc Feb 13 '18 at 10:28

2 Answers2

1

Obviously you would need to know the order of these objects, so I will assume you have an array of them, all parsed from JSON into JavaScript objects.

Secondly, I assume that a record that is a continuation of the previous one can be recognised by an empty balance field (for instance -- adapt as needed).

Here is code to perform the merge:

function mergeSplitObjects(arr) {
    return arr.filter( (curr, i) => {
        // Does this look like a split-off object that should be merged with previous?
        if (curr["Closing Balance"] !== "") { // Adapt condition as needed
            return true; // No, it is a real record
        }
        arr[i-1]["Narration"] += curr["Narration"]; // Merge, and filter curr out
    });
}

// Sample data with 3 records. First two should be merged
let arr = [
    {"Date":"19/02/16","Narration":"NEFT DR-BARB0PIMPAL-Govt. NE","Chq":{"/Ref":{"No":{"":"N050160130709970"}}},"Value Dt":"19/02/16","Withdrawal Amt":{"":"8,000.00"},"Deposit Amt":{"":""},"Closing Balance":"24,114.95"},
    {"Date":"","Narration":"TBANK, MUM-N050160130709970","Chq":{"/Ref":{"No":{"":""}}},"Value Dt":"","Withdrawal Amt":{"":""},"Deposit Amt":{"":""},"Closing Balance":""},
    {"Date":"20/02/16","Narration":"ATM NYC 13","Chq":{"/Ref":{"No":{"":"N050160130709971"}}},"Value Dt":"20/02/16","Withdrawal Amt":{"":"1,000.00"},"Deposit Amt":{"":""},"Closing Balance":"23,114.95"},
];
arr = mergeSplitObjects(arr);

console.log(arr);
.as-console-wrapper { max-height: 100% !important; top: 0; }
trincot
  • 317,000
  • 35
  • 244
  • 286
  • Great stuff trincot, I can see this approach would clearly win, thanks, Though I will test later today since I'm travelling, will mark as answer once I am done. – NBaua Feb 13 '18 at 05:26
  • Thanks trincot, you saved me from the mapping hell. – NBaua Feb 13 '18 at 06:19
1

I would use a function similar to Object.assign.

Just like Trincot, I assume Closing Balance to be an indication for records to merge.

var splitRegExp = /[a-z],\s*[a-z]/gi;
function deepMergingAssign(obj /*, sourceObjects*/){
    'use strict';
    if (obj == null) throw new TypeError('Cannot convert undefined or null to object');
    var final = Object(obj);
    [].slice.call(arguments, 1).forEach(function(arg){
        if(arg != null) {
            for(var prop in arg) {
                if (typeof arg[prop] === 'object'&&typeof final[prop] === 'object') {
                    // recursively call this function
                    arg[prop] = deepMergingAssign(final[prop],arg[prop]);
                    delete arg[prop]
                }
                else if(Object.prototype.hasOwnProperty.call(arg,prop)) {
                    // append the new values to the existing value.
                    var currentValue = final[prop].split(splitRegExp);
                    var incomingValue = arg[prop].split(splitRegExp);
                    incomingValue.forEach( function(val){
                        if (val! == '' && currentValue.indexOf(val) === -1) currentValue.push(val);
                    });
                    final[prop] = currentValue.join(', ');
                }
            }
        }
    });
    return final;
}

function mergeRecords(records){
    var toMerge = [];
    var mergedData = []
    for (var i=0; i<records.length; i++){
        // Change this condition as needed
        if (records[i]['Closing Balance'] !== '' && toMerge.length>0){
            // Create a merged record and reset the toMerge variable
            mergedData.push(deepMergingAssign.apply(null, toMerge));
            toMerge = [records[i]];
        }
        else {
            // This record should be merged with the previous.
            toMerge.push(records[i]);
        }
    }
    // Merge the last records stored in the array
    mergedData.push(deepMergingAssign.apply(null, toMerge));

    return mergedData;
}

var allRecords = [
    {"Date":"19/02/16","Narration":"NEFT DR-BARB0PIMPAL-Govt. NE","Chq":{"/Ref":{"No":{"":"N050160130709970"}}},"Value Dt":"19/02/16","Withdrawal Amt":{"":"8,000.00"},"Deposit Amt":{"":""},"Closing Balance":"24,114.95"},
    {"Date":"","Narration":"TBANK, MUM-N050160130709970","Chq":{"/Ref":{"No":{"":""}}},"Value Dt":"","Withdrawal Amt":{"":""},"Deposit Amt":{"":""},"Closing Balance":""},
    {"Date":"21/02/16","Narration":"TBANK","Chq":{"/Ref":{"No":{"":"N050160130709971"}}},"Value Dt":"21/02/16","Withdrawal Amt":{"":""},"Deposit Amt":{"":"2,000.00"},"Closing Balance":"26,114.95"},
    {"Date":"22/02/16","Narration":"TBANK","Chq":{"/Ref":{"No":{"":"N050160130709972"}}},"Value Dt":"22/02/16","Withdrawal Amt":{"":"5,750.00"},"Deposit Amt":{"":"1,000.00"},"Closing Balance":"21,364.95"},
    {"Date":"","Narration":"TBANK, MUM-N050160130709972","Chq":{"/Ref":{"No":{"":""}}},"Value Dt":"","Withdrawal Amt":{"":""},"Deposit Amt":{"":""},"Closing Balance":""}
]

var merged = mergeRecords(allRecords);
/* [
    record 1+2,
    record 3,
    record 4+5
   ] */
Kevin Drost
  • 383
  • 4
  • 7
  • Thanks Kevin, your stuff should work too, however trincot's approach is more cleaner, wish I could have marked your post as answer too. thanks again anyways. – NBaua Feb 13 '18 at 06:25