prince
prince

Reputation: 123

Merging JSON objects with same key together

I need to merge JSON objects with same key into one so that it gets an object or array(doesn't matter if result is an object or array) which holds the key and an array for the values

example JSON object:

[{
    "meine_frage": "hier kommt die antwort",
    "ne_andere_frage": "ne andere antwort",
    "was_willst_du": "alles",
    "mehr_zur_auswahl": ["einiges", "vieles und", "g\u00e4r nix"]

}, {
    "meine_frage": "tom & jerry",
    "ne_andere_frage": "mickey maus",
    "was_willst_du": "oder",
    "mehr_zur_auswahl": ["manches", "einiges", "vieles und", "g\u00e4r nix"]

}, {
    "meine_frage": "dick und doof",
    "ne_andere_frage": "minnie muas",
    "was_willst_du": "nichts",
    "mehr_zur_auswahl": ["g\u00e4r nix"]

}]

result should look like:

[{
    "meine_frage": ["hier kommt die antwort", "tom & jerry", "dick und doof"],
    "ne_andere_frage": ["ne andere antwort", "mickey maus", "minnie muas"],
    "was_willst_du": ["alles", "oder"],
    "mehr_zur_auswahl": ["einiges", "vieles und", "g\u00e4r nix", "manches", "einiges", "vieles und", "g\u00e4r nix"]
}]

some values are already arrays whereas others not, the keys are genterated dynamically so assume the the key name is unkown

i tried iterating over the key/values with $.each and for loops but without success, also searched the web but couldnt find similar, appreciate any help

Upvotes: 10

Views: 17946

Answers (7)

Nenad Vracar
Nenad Vracar

Reputation: 122027

You can use reduce() and concat() methods for this.

const data = [{"meine_frage":"hier kommt die antwort","ne_andere_frage":"ne andere antwort","was_willst_du":"alles","mehr_zur_auswahl":["einiges","vieles und","gär nix"]},{"meine_frage":"tom & jerry","ne_andere_frage":"mickey maus","was_willst_du":"oder","mehr_zur_auswahl":["manches","einiges","vieles und","gär nix"]},{"meine_frage":"dick und doof","ne_andere_frage":"minnie muas","was_willst_du":"nichts","mehr_zur_auswahl":["gär nix"]}]

// Use the `reduce` method to accumulate results into a single object.
const result = data.reduce(function(r, e) {
  // Iterate over each key in the current object.
  return Object.keys(e).forEach(function(k) {
    // Check if the key exists in the result object.
    if(!r[k]) r[k] = [].concat(e[k]) // If the key doesn't exist, initialize it as an array containing the value from the current object.       
    else r[k] = r[k].concat(e[k]) // If the key does exist, concatenate the existing array with the value from the current object.
  }), r // Return the updated result object for the next iteration.
}, {}) // Start with an empty object `{}` as the initial value of `result`.

console.log(result)

Upvotes: 13

Mohit Arora
Mohit Arora

Reputation: 150

The value gär nix appears three times in your example JSON file but only twice in the desired output. I have assumed that you intend to merge all keys without considering redundancy in the values. Based on this assumption, here is the code for it:

function mergeJsonObjects(jsonArray) {
  let mergedResult = {};

  // Loop over each JSON object in the array
  $.each(jsonArray, function (i, obj) {
    // Loop over each key-value pair in the current JSON object
    $.each(obj, function (key, value) {
      // Check if the key exists in the merged result, if not, initialize it as an array
      if (!mergedResult[key]) {
        mergedResult[key] = [];
      }

      // If the value is already an array, merge it with the existing array
      if (Array.isArray(value)) {
        mergedResult[key] = mergedResult[key].concat(value);
      } else {
        // Otherwise, just add the value into the array
        mergedResult[key].push(value);
      }
    });
  });

  return mergedResult;
}

// Your JSON Array
let jsonArray = [
  {
    meine_frage: "hier kommt die antwort",
    ne_andere_frage: "ne andere antwort",
    was_willst_du: "alles",
    mehr_zur_auswahl: ["einiges", "vieles und", "gär nix"],
  },
  {
    meine_frage: "tom & jerry",
    ne_andere_frage: "mickey maus",
    was_willst_du: "oder",
    mehr_zur_auswahl: ["manches", "einiges", "vieles und", "gär nix"],
  },
  {
    meine_frage: "dick und doof",
    ne_andere_frage: "minnie maus",
    was_willst_du: "nichts",
    mehr_zur_auswahl: ["gär nix"],
  },
];

let mergedJson = mergeJsonObjects(jsonArray);
console.log(JSON.stringify(mergedJson, null, 2));
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>

Upvotes: 0

edkeveked
edkeveked

Reputation: 18371

Using reduce and spread operator

var data = [{
    "meine_frage": "hier kommt die antwort",
    "ne_andere_frage": "ne andere antwort",
    "was_willst_du": "alles",
    "mehr_zur_auswahl": ["einiges", "vieles und", "g\u00e4r nix"]

}, {
    "meine_frage": "tom & jerry",
    "ne_andere_frage": "mickey maus",
    "was_willst_du": "oder",
    "mehr_zur_auswahl": ["manches", "einiges", "vieles und", "g\u00e4r nix"]

}, {
    "meine_frage": "dick und doof",
    "ne_andere_frage": "minnie muas",
    "was_willst_du": "nichts",
    "mehr_zur_auswahl": ["g\u00e4r nix"]

}]

let myData = data.reduce((b , a)=> {
    Object.keys(a).forEach(key => {
        if (Object.keys(b).indexOf(key) > -1) {
            if (typeof a[key] === "object") {
                b[key] = [...b[key], ...a[key]]       
            } else {
                b[key].push(a[key])
            }
             
        } else {
            if (typeof a[key] === "object") {
                b[key] = [...a[key]]
            } else {
                b[key] = [a[key]]
            }                  
        }    
    })
    return b
}, {})

console.log(myData)
.as-console-wrapper { max-height: 100% !important; top: 0; }

Upvotes: 2

Hassan Imam
Hassan Imam

Reputation: 22524

You can use array#reduce as a accumulator and iterate through each key of object and array#concat the values.

var data = [{ "meine_frage": "hier kommt die antwort", "ne_andere_frage": "ne andere antwort", "was_willst_du": "alles", "mehr_zur_auswahl": ["einiges", "vieles und", "g\u00e4r nix"] }, { "meine_frage": "tom & jerry", "ne_andere_frage": "mickey maus", "was_willst_du":"oder", "mehr_zur_auswahl": ["manches", "einiges", "vieles und", "g\u00e4r nix"] }, { "meine_frage": "dick und doof", "ne_andere_frage": "minnie muas", "was_willst_du": "nichts", "mehr_zur_auswahl": ["g\u00e4r nix"] }];

var merged = data.reduce((r,o) => {
  Object.keys(o).forEach(k => {
    r[k] = (r[k] || []).concat(o[k]);
  })
  return r;
},{});

console.log(merged);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Upvotes: 2

Mihai Alexandru-Ionut
Mihai Alexandru-Ionut

Reputation: 48337

You could use reduce method by passing a callback function as parameter.

The algorithm is follow: if final object already contains one key then you should initialize the key's value with an empty array. Otherwise, you should append to array value from all items from the array.

let data = [{"meine_frage":"hier kommt die antwort","ne_andere_frage":"ne andere antwort","was_willst_du":"alles","mehr_zur_auswahl":["einiges","vieles und","gär nix"]},{"meine_frage":"tom & jerry","ne_andere_frage":"mickey maus","was_willst_du":"oder","mehr_zur_auswahl":["manches","einiges","vieles und","gär nix"]},{"meine_frage":"dick und doof","ne_andere_frage":"minnie muas","was_willst_du":"nichts","mehr_zur_auswahl":["gär nix"]}]

let result = data.reduce(function(obj, item){
  Object.keys(item).forEach(function(key){
    if(!obj[key]) obj[key] = [].concat(item[key])
    else {
       if(Array.isArray(item[key]))
         obj[key].push(...item[key])
       else
         obj[key].push(item[key]);
    }
  });
  return obj;
},{});
console.log([result]);

Upvotes: 5

Sergio
Sergio

Reputation: 1364

This function will do the work:

const example = array => {
    let newObject = {}
    array.forEach((element) => {
        for(let key in element) {
            if(typeof element[key] === 'object') {
                element[key].forEach((el) => {
                    if(newObject[key] && newObject[key].length) {
                         newObject[key].push(el)
                    }
                    else {
                        newObject[key] = [el]
                    }
                })
            }
            else {
                if(newObject[key] && newObject[key].length){
                    newObject[key].push(element[key])
                }
                else{
                    newObject[key] = [element[key]]
                }
            }
        }
    })
    return newObject
}

Upvotes: 3

freelancer
freelancer

Reputation: 1164

Use map and check by Array.isArray, try below code

var myArray = [{"meine_frage": "hier kommt die antwort","ne_andere_frage": "ne andere antwort","was_willst_du": "alles","mehr_zur_auswahl": ["einiges", "vieles und", "g\u00e4r nix"]}, {"meine_frage": "tom & jerry","ne_andere_frage": "mickey maus","was_willst_du": "oder","mehr_zur_auswahl": ["manches", "einiges", "vieles und", "g\u00e4r nix"]}, {"meine_frage": "dick und doof","ne_andere_frage": "minnie muas","was_willst_du": "nichts","mehr_zur_auswahl": ["g\u00e4r nix"]}];

var findKeyOf = function(key){ 
  var temp = myArray.map(function(e){
    return e[key]; 
  });
  var test = [];
  for(let i in temp){
    if(Array.isArray(temp[i]) ){
      test = test.concat(temp[i]);
    }else{
      test.push(temp[i])
    }
  }
  return test;
};

var newArr = [
    {meine_frage:findKeyOf('meine_frage')},
    {ne_andere_frage:findKeyOf('ne_andere_frage')},
    {was_willst_du:findKeyOf('was_willst_du')},
    {mehr_zur_auswahl:findKeyOf('mehr_zur_auswahl')},
]
console.log(newArr);

Upvotes: 2

Related Questions