web-dev-qa-db-fra.com

Combinez ou fusionnez JSON sur node.js sans jQuery

J'ai plusieurs JSON comme ceux

var object1 = {name: "John"};
var object2 = {location: "San Jose"};

Ils ne nichent pas ou quelque chose comme ça. Juste fondamentalement des champs différents. Je dois les combiner en un seul JSON dans node.js comme ceci:

{name: "John", location: "San Jose"}

Je peux utiliser jQuery très bien. Voici un exemple de travail dans le navigateur:

http://jsfiddle.net/qhoc/agp54/

Mais si je fais ceci dans node.js, je ne veux pas charger jQuery (ce qui est un peu trop utilisé, plus jQuery de node.js ne fonctionne pas sur mon Windows machine).

Donc, y a-t-il un moyen simple de faire des choses similaires à $.extend() sans jQuery?

65
HP.

Une boucle normale? 

function extend(target) {
    var sources = [].slice.call(arguments, 1);
    sources.forEach(function (source) {
        for (var prop in source) {
            target[prop] = source[prop];
        }
    });
    return target;
}

var object3 = extend({}, object1, object2);

C'est un point de départ fondamental. Vous souhaiterez peut-être ajouter des éléments tels qu'une vérification hasOwnProperty ou une logique pour gérer le cas où plusieurs objets source possèdent une propriété portant le même identificateur.

Voici un exemple de travail .

Note latérale: ce que vous appelez "JSON" sont en fait des objets JavaScript normaux. JSON est simplement un format de texte qui partage une syntaxe avec JavaScript.

38
James Allardice

Vous devez utiliser " Object.assign () "

Inutile de réinventer la roue pour un cas d'utilisation aussi simple de la fusion superficielle.

La méthode Object.assign () est utilisée pour copier les valeurs de toutes les propriétés propres énumérables d'un ou plusieurs objets source vers un objet cible. Il retournera l'objet cible.

var o1 = { a: 1 };
var o2 = { b: 2 };
var o3 = { c: 3 };

var obj = Object.assign(o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 }
console.log(o1);  // { a: 1, b: 2, c: 3 }, target object itself is changed

Même les gens de Node.js le disent :

_extend n'a jamais été conçu pour être utilisé en dehors des modules internes de NodeJS. La communauté a trouvé et utilisé de toute façon . Il est obsolète et ne devrait pas être utilisé dans le nouveau code. JavaScript est livré avec une fonctionnalité intégrée très similaire via Object.assign.


Mettre à jour:

Vous pouvez utiliser le opérateur de propagation

Depuis version 8.6 , il est possible d'utiliser nativement l'opérateur spread dans Node.js. Exemple ci-dessous:

let o1 = { a: 1 };
let o2 = { b: 2 };
let obj = { ...o1, ...o2 }; // { a: 1, b: 2 }

Object.assign fonctionne toujours, cependant.


PS1: Si vous êtes réellement intéressé par la fusion deep (dans laquelle des données d'objet interne - dans n'importe quelle profondeur - sont fusionnées de manière récursive), vous pouvez utiliser des packages tels que deepmerge , assign-deep ou lodash.merge , qui sont plutôt petits et simples à utiliser .

PS2: N'oubliez pas que Object.assign ne fonctionne pas avec les versions 0.X de Node.js. Si vous travaillez avec l'une de ces versions (vous ne devriez vraiment pas le faire maintenant), vous pouvez utiliser require("util")._extend comme indiqué dans le lien Node.js ci-dessus - pour plus de détails, consultez la réponse de tobymackenzie à cette même question .

85
Ricardo Nolde

Si vous utilisez la version Node> = 4, utilisez Object.assign() (voir la réponse de Ricardo Nolde ).

Si vous utilisez le noeud 0.x, il y a le util in_extend intégré:

var extend = require('util')._extend
var o = extend({}, {name: "John"});
extend(o,  {location: "San Jose"});

Il ne fait pas de copie en profondeur et n'autorise que deux arguments à la fois, mais il est intégré. J'ai vu ceci mentionné dans une question sur le clonage d'objets dans noeud: https://stackoverflow.com/a/15040626 .

Si vous souhaitez utiliser une méthode "privée", vous pouvez toujours utiliser un proxy:

// myutil.js
exports.extend = require('util')._extend;

et remplacez-le par votre propre implémentation si elle disparaît un jour. C'est (approximativement) leur mise en oeuvre:

exports.extend = function(Origin, add) {
    if (!add || (typeof add !== 'object' && add !== null)){
        return Origin;
    }

    var keys = Object.keys(add);
    var i = keys.length;
    while(i--){
        Origin[keys[i]] = add[keys[i]];
    }
    return Origin;
};
55
tobymackenzie

Underscore's extend est le moyen le plus simple et le plus rapide d'y parvenir, comme l'a commenté James.

Voici un exemple utilisant le trait de soulignement:

var _ = require('underscore'), // npm install underscore to install
  object1 = {name: "John"},
  object2 = {location: "San Jose"};

var target = _.extend(object1, object2);

object 1 obtiendra les propriétés de object2 et sera renvoyé et affecté à target . Vous pouvez le faire comme ceci, selon que l'objet que vous souhaitez modifier soit:

var target = {};
_.extend(target, object1, object2);
50
AndyD

Utilisez merge .

$ npm install merge

Exemple de code:

var merge = require('merge'), // npm install -g merge
    original, cloned;

console.log(

    merge({ one: 'hello' }, { two: 'world' })

); // {"one": "hello", "two": "world"}

original = { x: { y: 1 } };

cloned = merge(true, original);

cloned.x.y++;

console.log(original.x.y, cloned.x.y); // 1, 2
15
zim

Je vois que ce fil est trop ancien, mais je mets ma réponse ici uniquement pour la journalisation.

Dans l'un des commentaires ci-dessus, vous avez indiqué que vous souhaitiez utiliser 'express' dans votre projet qui a la bibliothèque 'connect' dans le fichier liste de dépendance. En réalité, la bibliothèque 'connect.utils' contient une 'fusion' méthode qui fait le tour. Vous pouvez donc utiliser le tiers mise en œuvre sans ajouter de nouvelles bibliothèques tierces.

12
Petr KOKOREV

Voici une solution simple, pour fusionner JSON . J'ai fait ce qui suit.

  • Convertissez chacun des fichiers JSON en chaînes à l'aide de JSON.stringify(object).
  • Concaténez toutes les chaînes JSON à l'aide de l'opérateur +.
  • Remplacez le modèle /}{/g par ","
  • Analyser la chaîne de résultat en objet JSON

    var object1 = {name: "John"};
    var object2 = {location: "San Jose"};
    var merged_object = JSON.parse((JSON.stringify(object1) + JSON.stringify(object2)).replace(/}{/g,","))
    

Le JSON fusionné résultant sera

{name: "John", location: "San Jose"}
10
Manu K Mohan

Il existe un moyen facile de le faire dans Node.js

var object1 = {name: "John"};
var object2 = {location: "San Jose"};

Pour combiner/étendre cela, nous pouvons utiliser l'opérateur ... dans ECMA6.

var object1 = {name: "John"};
var object2 = {location: "San Jose"};

var result = {
  ...object1,
  ...object2
}

console.log(result)

3
Stenal P Jolly

Vous pouvez également utiliser ce paquet npm léger appelé absorber

Il s'agit de 27 lignes de code, 1 Ko et utilise la récursion pour effectuer des fusions d'objets approfondies.

var absorb = require('absorb');
var obj1, obj2;

obj1 = { foo: 123, bar: 456 };
obj2 = { bar: 123, key: 'value' }

absorb(obj1, obj2);

console.log(obj1); // Output: { foo: 123, bar: 123, key: 'value' }

Vous pouvez également l'utiliser pour créer un clone ou ne transférer que des valeurs si elles n'existent pas dans l'objet source. La procédure à suivre est décrite dans le lien fourni.

3
Patrick Murphy

Cela peut être facilement fait en utilisant la méthode Object.assign () -

 var object1 = {name: "John"};
 var object2 = {location: "San Jose"};
 var object3 = Object.assign(object1,object2);
 console.log(object3);

maintenant objet3 est {nom: 'John', emplacement: 'San Jose'}

2
Sushil Kumar

Lodash est une autre option de ceinture à outils puissante pour ce type d’utilitaire. Voir: _.merge() (qui est récursif)

var object = {
  'a': [{ 'b': 2 }, { 'd': 4 }]
};
var other = {
  'a': [{ 'c': 3 }, { 'e': 5 }]
}; 
_.merge(object, other);
// => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] } 
2
JoshuaDavid

Si vous avez besoin de comportements spéciaux tels que l'extension d'objet imbriqué ou le remplacement de tableau, vous pouvez utiliser extendify de Node.js.

var extendify = require('extendify');

_.extend = extendify({
    inPlace: false,
    arrays : 'replace',
    isDeep: true
});

obj1 = {
    a:{
        arr: [1,2]
    },
    b: 4
};

obj2 = {
    a:{
        arr: [3]
    }
};

res = _.extend(obj1,obj2);
console.log(JSON.stringify(res)); //{'a':{'arr':[3]},'b':4}
2
user1928072

Le code ci-dessous vous aidera à fusionner deux objets JSON contenant des objets imbriqués.

function mergeJSON(source1,source2){
    /*
     * Properties from the Souce1 object will be copied to Source2 Object.
     * Note: This method will return a new merged object, Source1 and Source2 original values will not be replaced.
     * */
    var mergedJSON = Object.create(source2);// Copying Source2 to a new Object

    for (var attrname in source1) {
        if(mergedJSON.hasOwnProperty(attrname)) {
          if ( source1[attrname]!=null && source1[attrname].constructor==Object ) {
              /*
               * Recursive call if the property is an object,
               * Iterate the object and set all properties of the inner object.
              */
              mergedJSON[attrname] = zrd3.utils.mergeJSON(source1[attrname], mergedJSON[attrname]);
          } 

        } else {//else copy the property from source1
            mergedJSON[attrname] = source1[attrname];

        }
      }

      return mergedJSON;
}
1
shibualexis

Utilisez l'opérateur spread. Il est supporté dans Node depuis la version 8.6

const object1 = {name: "John"};
const object2 = {location: "San Jose"};

const obj = {...object1, ...object2}

console.log(obj)
//   {
//     "name": "John",
//     "location": "San Jose"
//   }

1
Khaled Bin A Quadir

Vous pouvez utiliser Lodash

const _ = require('lodash');

let firstObject = {'email' : '[email protected]};
let secondObject = { 'name' : { 'first':message.firstName } };
_.merge(firstObject, secondObject)
1
Aslan Varoqua

Vous pouvez le faire en ligne, sans changer aucune variable comme celle-ci:

let obj1 = { name: 'John' };
let obj2 = { surname: 'Smith' };
let obj = Object.assign({}, obj1, obj2); // { name: 'John', surname: 'Smith' }
0
Emre Tapcı

Une meilleure approche de la solution correcte ici afin de ne pas modifier la cible:

function extend(){
  let sources = [].slice.call(arguments, 0), result = {};
  sources.forEach(function (source) {
    for (let prop in source) {
      result[prop] = source[prop];
    }
  });
  return result;
}
0
Dody