Об'єднати або об'єднати JSON на node.js без jQuery


77

У мене є кілька JSONтаких

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

Вони не гніздяться або щось подібне. Просто в основному різні поля. Мені потрібно об'єднати їх в один сингл JSONу node.js так:

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

Я можу використовувати jQuery просто чудово. Ось робочий приклад у браузері:

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

Але якщо я роблю це в node.js , я не хочу завантажувати jQuery (що трохи перевикористовує, плюс jQuery node.js не працює на моїй машині Windows ).

Тож чи є простий спосіб робити подібні справи $.extend()без jQuery ?


2
Якщо ви робите різні речі, подібні до цього, ви можете розглянути можливість використання підкреслення , яке доступне як модуль Node .
James Allardice,


FYI Object.assign робить це, але, на жаль, наразі це не підтримується. Сподіваємось, колись скоро! developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Рене Вуллер,

1
Це не JSON, ви просто створюєте стандартні об'єкти JS, використовуючи буквальні нотації. (Наприклад, у клавішах JSON мають бути рядки). І коли ви "об'єднуєте" ці об'єкти, це має нульове відношення до JSON.
UpTheCreek

Відповіді:


42

Нормальний цикл?

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);

Це основна відправна точка. Можливо, ви захочете додати такі речі, як hasOwnPropertyчек, або додати якусь логіку для обробки випадку, коли кілька вихідних об'єктів мають властивість з однаковим ідентифікатором.

Ось робочий приклад .

Примітка : те, що ви називаєте "JSON", насправді є звичайними об'єктами JavaScript. JSON - це просто текстовий формат, який використовує певний синтаксис із JavaScript.


Я використовую цю функцію для об'єднання двох json. Але отриманий json має префікс "0". Приклад 0: {kye: value}. Будь ласка, допоможіть мені, як мені додати префікс до власного рядка замість "0"?
Saurabh Ghewari

7
Принижений голос, оскільки це один із випадків, коли людей, особливо початківців, слід направляти до перевірених бібліотек.
Martin Wawrusch

122

Ви повинні використовувати " Object.assign () "

Немає необхідності винаходити колесо для такого простого випадку неглибокого злиття.

Метод Object.assign () використовується для копіювання значень усіх перелічених власних властивостей з одного або кількох вихідних об'єктів у цільовий об'єкт. Він поверне цільовий об'єкт.

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

Навіть люди з Node.js говорять так :

_extendніколи не був призначений для використання поза внутрішніми модулями NodeJS. Спільнота все одно знайшла і використовувала його. Він застарілий і не повинен використовуватися в новому коді. JavaScript поставляється з дуже подібною вбудованою функціональністю через Object.assign.


Оновлення:

Ви можете використовувати оператор поширення

З версії 8.6 можна оперативно використовувати оператор поширення в Node.js. Приклад нижче:

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

Object.assign все ще працює, хоча.


PS1 : Якщо ви насправді зацікавлені в глибокому об’єднанні (при якому дані внутрішнього об’єкта - в будь-якій глибині - рекурсивно об’єднуються), ви можете використовувати такі пакети, як deepmerge , assign-deep або lodash.merge , які досить малі та прості для використання.

PS2 : Майте на увазі , що Object.assign не працює з 0.X версії Node.js . Якщо ви працюєте з однією з цих версій (до цього часу вам цього не слід було робити ), ви можете скористатися, require("util")._extendяк показано в посиланні Node.js вище - для отримання детальної інформації перевірте відповідь tobymackenzie на це саме питання .


1
+1 Кожному, хто приходить сюди, шукаючи альтернативу власного веб-переглядача , зауважте, що це функція ES6 і як така ще недостатньо підтримується .
Боаз,

Додавши коментар до Boaz , у посиланні Mozilla Object.assignвище, ви можете знайти полізаповнювач, який чудово працює у браузері.
Рікардо Нольде

3
Зателефонуйте йому з пустим першим аргументом, щоб уникнути випадкового спотворення ваших предметів:var obj = Object.assign({}, o1, o2, o3)
pguardiario

57

Якщо використовується версія Node> = 4, використовуйте Object.assign() (див. Відповідь Рікардо Нольде ).

Якщо використовується Node 0.x, є вбудований util._extend:

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

Він не робить глибокої копії і допускає лише два аргументи одночасно, але вбудований. Я бачив це згадане у питанні про клонування об’єктів у вузлі: https://stackoverflow.com/a/15040626 .

Якщо ви стурбовані використанням "приватного" методу, ви завжди можете його застосувати:

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

і замініть його власною реалізацією, якщо вона коли-небудь зникне. Це (приблизно) їх реалізація:

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;
};

5
Підкреслення в _extend представляє приватний метод, тобто він не призначений для загального використання. Цей метод не тільки не оформлений документально, але впровадження може змінитися в будь-якій редакції, що вплине на ваш проект.
aaaaaa

3
Як @jimbojw згадав у коментарі до пов'язаної відповіді, Ісаак каже: "Ви можете продовжувати і використовувати util._extends()... Це скоро нікуди не піде" . У цій темі є подальше обговорення. Якщо ви стурбовані, прочитайте і прийміть рішення щодо свого проекту.
tobymackenzie

npm install util-extension
Мацей Кравчик

1
_extend()функція beeen засуджується на користь Object.Assign()- developer.mozilla.org/en-US/docs/Web/JavaScript/Reference / ...
brasskazoo

51

Підкресленняextend - це найпростіший і найшвидший спосіб досягти цього, як прокоментував Джеймс.

Ось приклад використання підкреслення:

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

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

object 1 отримає властивості object2 і буде повернутий і призначений цільовій. Ви можете зробити це так само, залежно від того, чи не проти ви модифікуєте object1:

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

1
Дякую. Але хотів би уникати підкреслення в node.js, якщо я можу.
HP.

1
У мене просто є легкий додаток node.js із лише express та mailjs. Просто не хочу завантажувати інші бібліотеки, якщо я використовую лише одну функцію. Ідея Ура все ще крута. Дякую.
HP.

10
Обережно, розширення підкреслення лише на першому рівні. Він не може об’єднати субоєкти.
Feugy

15

Використовуйте злиття .

$ npm install merge

Зразок коду:

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

2
Відмінно! Дякуємо, що поділились цим.
Гор

12

Я бачу, що цей потік занадто старий, але я помістив свою відповідь тут просто для ведення журналу.

В одному з коментарів вище ви згадали, що хочете використовувати 'express' у своєму проекті, який має бібліотеку 'connect' у списку залежностей. Насправді бібліотека 'connect.utils' містить метод 'злиття', який робить трюк. Таким чином, ви можете використовувати сторонні реалізації без додавання нових сторонніх бібліотек.


11

Ось просте рішення - об’єднати JSON. Я зробив наступне.

  • Перетворіть кожен з JSON у рядки за допомогою JSON.stringify(object).
  • Об'єднайте всі рядки JSON за допомогою +оператора.
  • Замініть шаблон /}{/gна","
  • Проаналізуйте рядок результату назад до об’єкта JSON

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

Отриманий об'єднаний JSON буде

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

Чи спрацювало б це, якщо всередині подвійних лапок (значення) є {або}? Я завжди соромлюся зламати рядок.
HP.

@ HP. Так, це спрацює. Це досить прямий звичайний регулярний вираз /} {/, не потрібно турбуватися про маніпуляції рядками. :-)
Ману К Мохан

1
На жаль, це не працює, якщо, object2 = {}оскільки остаточні символи, які слід проаналізувати, є ,}. Це можна вирішити, додавши після заміни:.replace(/,}^/, '}')
htaidirt

3
Використовуйте будь-яку кількість аргументів, незалежно від того, чи є хтось порожнім, з gist.github.com/rxaviers/6734630
Рафаель Ксав'єр

Реквізит @RafaelXavier Його суть перетворює цю відповідь на корисну функцію.
scarver2

3

Ви також можете використовувати цей легкий пакет npm, який називається absorb

Це 27 рядків коду, 1 кб і використовує рекурсію для глибокого об’єднання об’єктів.

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' }

Ви також можете використовувати його для створення клону або передавання значень лише у тому випадку, якщо вони не існують у вихідному об'єкті, як це зробити детально описано у наданому посиланні.


3

Це легко зробити за допомогою методу Object.assign () -

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

тепер object3 - це {name: 'John', location: 'San Jose'}


У вашому прикладі object1також змінено. Перевірте мою відповідь, щоб дізнатися більше.
Рікардо Нольде,

3

Існує простий спосіб зробити це в Node.js

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

Щоб поєднати / розширити це, ми можемо використовувати ...оператор у ECMA6

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

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

console.log(result)


2

Якщо вам потрібно спеціальні моделі поводження , як вкладене розширення об'єкта або заміна масиву ви можете використовувати Node.js в extendify .

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}

1
Щоб бути точним: Extendify - це не Node.js. Це пакет для Node.js.
Лео Гербер

2

Lodash - ще один потужний варіант інструментального пояса для таких видів комунальних послуг. Див .: _.merge()(що є рекурсивним)

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

Використовуйте оператор поширення. Він підтримується в Node з версії 8.6

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

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

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


1
Привіт Халед, ти повинен спробувати пояснити, що робить оператор поширення, оскільки це покращить твій пост. Пояснення набагато кращі, ніж просто вказівка ​​коду. Це також дублікат вже розміщеної відповіді.
R. Chappell

1

Можна використовувати Lodash

const _ = require('lodash');

let firstObject = {'email' : 'email@email.com};
let secondObject = { 'name' : { 'first':message.firstName } };
_.merge(firstObject, secondObject)

0

Наведений нижче код допоможе вам об’єднати два об’єкти JSON, які мають вкладені об’єкти.

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;
}

0

Кращий підхід від правильного рішення тут, щоб не змінювати ціль:

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

Ви можете зробити це вбудовано, не змінюючи таких змінних, як це:

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

-3

Нехай object1і object2буде два об'єкти JSON.

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

object1.push(object2);

Це просто додасться object2до object1:

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

Це не те, що запитував ОП. Ви показуєте, як створити масив об’єктів JSON. OP запитав спосіб поєднати пари ключ: значення з декількох об'єктів JSON в один.
Девід Макогон,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.