Cómo Fusionar JSON
2025/05/20
9 min de lectura

Cómo Fusionar JSON

Guía completa para fusionar objetos JSON en diferentes lenguajes de programación

Introducción a la Fusión de JSON

La fusión de objetos JSON es una operación fundamental en el procesamiento de datos, la gestión de configuraciones y las interacciones con API. Ya sea que estés combinando configuraciones de usuario, fusionando archivos de configuración o agregando respuestas de API, entender cómo fusionar correctamente objetos JSON es crucial para el desarrollo moderno.

La fusión de JSON se refiere al proceso de combinar dos o más objetos JSON en un único objeto unificado. Este proceso puede ser simple para objetos planos, pero se vuelve más complejo cuando se trata de estructuras anidadas, arrays y valores conflictivos.

Conceptos Básicos de Fusión de JSON

Antes de adentrarnos en los detalles de implementación, es importante entender algunos conceptos clave relacionados con la fusión de JSON:

Fusión Superficial vs Fusión Profunda

  • Fusión Superficial: Solo se combinan las propiedades de nivel superior. Cuando ambos objetos contienen la misma propiedad, el valor del segundo objeto sobrescribe al primero.
  • Fusión Profunda: La operación de fusión recorre recursivamente el árbol del objeto, combinando objetos anidados en lugar de reemplazarlos.

Estrategias de Fusión para Valores en Conflicto

Cuando se fusionan objetos JSON, los valores en conflicto pueden manejarse de varias maneras:

EstrategiaDescripciónCaso de Uso
Último GanaEl valor del último objeto anula los valores anterioresConfiguraciones predeterminadas
Primero GanaSe conserva el valor del primer objetoPreservar configuraciones de usuario
Lógica PersonalizadaAplicar lógica específica para diferentes propiedadesReglas de negocio complejas
Error en ConflictoGenerar un error cuando se detectan conflictosIntegridad crítica de datos

Métodos de JavaScript para Fusionar JSON

JavaScript ofrece varios métodos incorporados para fusionar objetos JSON:

Usando Object.assign()

El método Object.assign() realiza una fusión superficial, copiando todas las propiedades enumerables propias de los objetos fuente a un objeto destino.

const json1 = { name: "John", age: 30 };
const json2 = { city: "New York", age: 31 };

const merged = Object.assign({}, json1, json2);
console.log(merged);
// Salida: { name: "John", city: "New York", age: 31 }

Observa que las propiedades con la misma clave son sobrescritas por los objetos que aparecen más tarde en la lista de parámetros.

Usando el Operador de Propagación (...)

El operador de propagación proporciona una forma más concisa de fusionar objetos:

const json1 = { name: "John", age: 30 };
const json2 = { city: "New York", age: 31 };

const merged = { ...json1, ...json2 };
console.log(merged);
// Salida: { name: "John", city: "New York", age: 31 }

Este método también sobrescribe las claves duplicadas con valores de objetos posteriores.

Fusión Profunda de Objetos JSON

Tanto Object.assign() como el operador de propagación realizan fusiones superficiales. Para objetos anidados, necesitas una implementación de fusión profunda:

Función Recursiva de Fusión Profunda

function deepMerge(target, source) {
  const output = Object.assign({}, target);
  
  if (isObject(target) && isObject(source)) {
    Object.keys(source).forEach(key => {
      if (isObject(source[key])) {
        if (!(key in target)) {
          Object.assign(output, { [key]: source[key] });
        } else {
          output[key] = deepMerge(target[key], source[key]);
        }
      } else {
        Object.assign(output, { [key]: source[key] });
      }
    });
  }
  
  return output;
}

function isObject(item) {
  return (item && typeof item === 'object' && !Array.isArray(item));
}

// Uso
const json1 = { 
  name: "John", 
  address: { 
    city: "New York", 
    zip: 10001 
  } 
};

const json2 = { 
  name: "Jane", 
  address: { 
    state: "NY" 
  } 
};

const merged = deepMerge(json1, json2);
console.log(merged);
// Salida: { 
//   name: "Jane", 
//   address: { 
//     city: "New York", 
//     zip: 10001, 
//     state: "NY" 
//   } 
// }

Uso de Bibliotecas para Fusionar JSON

Para escenarios de fusión más complejos, considera usar bibliotecas establecidas:

merge y mergeWith de Lodash

Lodash proporciona funciones robustas para la fusión profunda:

const _ = require('lodash');

const json1 = { user: { name: "John", data: [1, 2] } };
const json2 = { user: { age: 30, data: [3, 4] } };

// Fusión profunda básica
const merged1 = _.merge({}, json1, json2);
console.log(merged1);
// Salida: { user: { name: "John", age: 30, data: [3, 4] } }

// Fusión personalizada con mergeWith
const merged2 = _.mergeWith({}, json1, json2, (objValue, srcValue) => {
  if (Array.isArray(objValue)) {
    return objValue.concat(srcValue);
  }
});
console.log(merged2);
// Salida: { user: { name: "John", age: 30, data: [1, 2, 3, 4] } }

Paquete deepmerge

El paquete npm deepmerge está específicamente diseñado para la fusión profunda:

const deepmerge = require('deepmerge');

const json1 = { user: { name: "John", hobbies: ["reading"] } };
const json2 = { user: { age: 30, hobbies: ["swimming"] } };

// Fusión predeterminada (concatena arrays)
const merged = deepmerge(json1, json2);
console.log(merged);
// Salida: { user: { name: "John", age: 30, hobbies: ["reading", "swimming"] } }

// Fusión personalizada de arrays
const overwriteMerge = (destinationArray, sourceArray) => sourceArray;
const options = { arrayMerge: overwriteMerge };
const mergedCustom = deepmerge(json1, json2, options);
console.log(mergedCustom);
// Salida: { user: { name: "John", age: 30, hobbies: ["swimming"] } }

Fusionando JSON en Otros Lenguajes

Python

Usando el método de actualización de diccionarios incorporado:

import json

json1_str = '{"name": "John", "age": 30}'
json2_str = '{"city": "New York", "age": 31}'

# Parsear cadenas JSON a diccionarios
json1 = json.loads(json1_str)
json2 = json.loads(json2_str)

# Fusionar diccionarios
merged = {**json1, **json2}  # Python 3.5+

# Convertir de vuelta a cadena JSON
merged_json = json.dumps(merged)
print(merged_json)
# Salida: {"name": "John", "city": "New York", "age": 31}

Para fusión profunda en Python:

def deep_merge(dict1, dict2):
    result = dict1.copy()
    for key, value in dict2.items():
        if key in result and isinstance(result[key], dict) and isinstance(value, dict):
            result[key] = deep_merge(result[key], value)
        else:
            result[key] = value
    return result

json1 = {"user": {"name": "John", "settings": {"theme": "dark"}}}
json2 = {"user": {"age": 30, "settings": {"notifications": True}}}

merged = deep_merge(json1, json2)
print(merged)
# Salida: {'user': {'name': 'John', 'settings': {'theme': 'dark', 'notifications': True}, 'age': 30}}

Ruby

Usando el método Hash#merge:

require 'json'

json1_str = '{"name": "John", "age": 30}'
json2_str = '{"city": "New York", "age": 31}'

# Parsear cadenas JSON a hashes
json1 = JSON.parse(json1_str)
json2 = JSON.parse(json2_str)

# Fusionar hashes
merged = json1.merge(json2)

# Convertir de vuelta a cadena JSON
merged_json = JSON.generate(merged)
puts merged_json
# Salida: {"name":"John","city":"New York","age":31}

Para fusión profunda en Ruby:

require 'json'

# deep_merge incorporado en Ruby
require 'active_support/core_ext/hash/deep_merge'

json1 = JSON.parse('{"user": {"name": "John", "settings": {"theme": "dark"}}}')
json2 = JSON.parse('{"user": {"age": 30, "settings": {"notifications": true}}}')

merged = json1.deep_merge(json2)
puts JSON.generate(merged)
# Salida: {"user":{"name":"John","settings":{"theme":"dark","notifications":true},"age":30}}

Casos Especiales de Fusión

Fusión de Arrays

Cuando se fusionan objetos JSON que contienen arrays, tienes varias estrategias:

  1. Reemplazar: Los arrays posteriores reemplazan completamente a los anteriores
  2. Concatenar: Combinar los elementos de ambos arrays
  3. Fusión por índice: Fusionar elementos de array en las mismas posiciones
  4. Fusión por ID: Fusionar elementos de array basados en un campo identificador
// Ejemplo de concatenación de arrays
const json1 = { tags: ["important", "urgent"] };
const json2 = { tags: ["completed", "archived"] };

const merged = {
  ...json1,
  tags: [...json1.tags, ...json2.tags]
};
console.log(merged);
// Salida: { tags: ["important", "urgent", "completed", "archived"] }

// Ejemplo de fusión de arrays por ID
const users1 = { users: [{ id: 1, name: "John" }, { id: 2, name: "Jane" }] };
const users2 = { users: [{ id: 1, age: 30 }, { id: 3, name: "Bob", age: 25 }] };

function mergeArraysById(arr1, arr2, idKey) {
  const merged = [...arr1];
  
  arr2.forEach(item2 => {
    const item1Index = merged.findIndex(item1 => item1[idKey] === item2[idKey]);
    
    if (item1Index >= 0) {
      merged[item1Index] = { ...merged[item1Index], ...item2 };
    } else {
      merged.push(item2);
    }
  });
  
  return merged;
}

const mergedUsers = {
  users: mergeArraysById(users1.users, users2.users, 'id')
};

console.log(mergedUsers);
// Salida: {
//   users: [
//     { id: 1, name: "John", age: 30 },
//     { id: 2, name: "Jane" },
//     { id: 3, name: "Bob", age: 25 }
//   ]
// }

Manejo de Valores null y undefined

Al fusionar objetos, debes decidir cómo manejar los valores null y undefined:

const json1 = { name: "John", age: null, city: undefined };
const json2 = { age: 30 };

// Comportamiento predeterminado (los valores null se copian, los undefined se ignoran)
const merged1 = Object.assign({}, json1, json2);
console.log(merged1);
// Salida: { name: "John", age: 30 }

// Manejo personalizado en fusión profunda
function customDeepMerge(target, source) {
  const output = Object.assign({}, target);
  
  if (isObject(target) && isObject(source)) {
    Object.keys(source).forEach(key => {
      // Omitir valores null en la fuente
      if (source[key] === null) return;
      
      if (isObject(source[key])) {
        if (!(key in target)) {
          output[key] = source[key];
        } else {
          output[key] = customDeepMerge(target[key], source[key]);
        }
      } else {
        output[key] = source[key];
      }
    });
  }
  
  return output;
}

Herramientas de Línea de Comandos para Fusionar JSON

Usando jq

jq es un potente procesador JSON de línea de comandos que puede fusionar archivos JSON:

# Fusionar dos archivos JSON
jq -s '.[0] * .[1]' file1.json file2.json > merged.json

# Fusión profunda con manejo personalizado de arrays
jq -s '.[0] * .[1] | .array = (.[0].array + .[1].array)' file1.json file2.json > merged.json

Usando Node.js

Puedes crear un script simple para fusionar archivos JSON con Node.js:

const fs = require('fs');
const _ = require('lodash');

// Leer archivos JSON
const file1 = JSON.parse(fs.readFileSync('file1.json', 'utf8'));
const file2 = JSON.parse(fs.readFileSync('file2.json', 'utf8'));

// Fusionar objetos
const merged = _.merge({}, file1, file2);

// Escribir resultado
fs.writeFileSync('merged.json', JSON.stringify(merged, null, 2));

Mejores Prácticas para Fusionar JSON

  1. Sé explícito sobre claves duplicadas: Comprende cómo el método elegido maneja los conflictos de claves
  2. Considera la inmutabilidad: Crea nuevos objetos en lugar de modificar los existentes
  3. Maneja la fusión profunda con cuidado: Utiliza métodos recursivos adecuados o bibliotecas para objetos anidados
  4. Valida el resultado fusionado: Asegúrate de que el objeto final tenga una estructura válida
  5. Prueba con casos límite: Objetos vacíos, valores nulos, estructuras profundamente anidadas
  6. Documenta tu estrategia de fusión: Deja claro cómo se resuelven los conflictos
  7. Considera el rendimiento: Para objetos grandes, algunas implementaciones de fusión profunda pueden ser ineficientes

Conclusión

La fusión de objetos JSON es una operación común pero con matices. La estrategia de fusión apropiada depende de tus requisitos específicos, la estructura de datos y el entorno del lenguaje. Al comprender las diversas técnicas de fusión y sus implicaciones, puedes combinar eficazmente datos de diferentes fuentes mientras mantienes la integridad de los datos y satisfaces las necesidades de tu aplicación.

Autor

avatar for Corey
Corey

Categorías

Boletín

Únete a la comunidad

Suscríbete a nuestro boletín para recibir las últimas noticias y actualizaciones