Merging JSON objects with same key together
Asked Answered
J

7

10

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

Johnjohna answered 21/12, 2017 at 11:17 Comment(2)
where is your js code?Burglar
thank you all for your quick answersJohnjohna
F
13

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)
Felisha answered 21/12, 2017 at 11:32 Comment(1)
This is good and quite close to being functional. With a few tweaks you could make it so: replace the if/else and assignments with a ternary return statement, and use that function in array_map_associative.Wordsmith
D
5

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]);
Dissemblance answered 21/12, 2017 at 11:26 Comment(0)
C
3

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
}
Corrugate answered 21/12, 2017 at 11:40 Comment(0)
S
2

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);
Soil answered 21/12, 2017 at 11:35 Comment(0)
P
2

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; }
Phosphene answered 21/12, 2017 at 11:45 Comment(0)
F
2

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; }
Fitly answered 21/12, 2017 at 11:50 Comment(2)
Where did you used destructing assignment ?Dissemblance
@MihaiAlexandru-Ionut, I updated my answer. It is the spread operatorFitly
W
0

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>
Warrenwarrener answered 30/8, 2024 at 5:25 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.