TehShrike / deepmerge

A library for deep (recursive) merging of Javascript objects
MIT License
2.75k stars 216 forks source link

How to use one object as target #233

Closed Stevemoretz closed 3 years ago

Stevemoretz commented 3 years ago

I have two objects for example :

const oneVariable = {one : 1,two : 2};
const twoVariable = {two : 3};

I want twoVariable to be my target. So basically the result should be {two : 3} and one property must be removed. So I want only the changes of twoVariable to be added to the result and anything it has lost should be removed too.

Currently you have such a behavior for overriding, tow from twoVariable overrides oneVariable.two but the result has one : 1 in it, which should be removed.

Is this possible?

RebeccaStevens commented 3 years ago

It's not something the library is really designed for but it is possible using customMerge.

const deepmerge = require("deepmerge");

const oneVariable = {one : 1,two : 2};
const twoVariable = {two : 3};

const customMerge = () => (a, b) => {
  const mergedResult = deepmerge(a, b, { customMerge });

  for (const keyA of Object.keys(a)) {
    if (!Object.prototype.hasOwnProperty.call(b, keyA)) {
      delete mergedResult[keyA];
    }
  }

  return mergedResult;
};

const result = customMerge()(
  oneVariable,
  twoVariable
);

console.log(result);
Stevemoretz commented 3 years ago

It's not something the library is really designed for but it is possible using customMerge.

const deepmerge = require("deepmerge");

const oneVariable = {one : 1,two : 2};
const twoVariable = {two : 3};

const customMerge = () => (a, b) => {
  const mergedResult = deepmerge(a, b, customMerge);

  for (const keyA of Object.keys(a)) {
    if (!Object.prototype.hasOwnProperty.call(b, keyA)) {
      delete mergedResult[keyA];
    }
  }

  return mergedResult;
};

const result = customMerge()(
  oneVariable,
  twoVariable
);

console.log(result);

Wow thank you so much Rebecca, just one question I haven't tested your code yet. Does it support infinite nested object properties or only one level?

RebeccaStevens commented 3 years ago

I haven't tested it but it should support nested properties. The customMerge is telling deep merge how to merge for each merge it performs.

RebeccaStevens commented 3 years ago

Just noticed a small mistake in my code. Should be fixed now.

Stevemoretz commented 3 years ago

Thanks yeah I checked it now but it doesn't seem to go all the way through.

    console.log(customMerge()({
        "default": {
            "init": {
                "body": {
                    "hello": "ads",
                    "hi": "2",
                    "password1": "s",
                },
            },
        },
    }, {
        "default": {
            "init": {
                "body": {
                    "hello": "ads",
                    "password1": "s",
                },
            },
        },
    }));

In my real example I had these two objects hi property should be removed. I tried customMerge before you mention it and couldn't get it to that level. The code that you provided also doesn't reach to that it only gets to "default".

This is the result right now :

Object {
  "default": Object {
    "init": Object {
      "body": Object {
        "hello": "ads",
        "hi": "2",
        "password1": "s",
      },
    },
  },
}
RebeccaStevens commented 3 years ago

I just tested it and it was working for me. I think you tried running the version with a small mistake in - recopy the code (not the code you quoted).

Make sure the call to deepmerge looks like this:

const mergedResult = deepmerge(A, B, { customMerge });
Stevemoretz commented 3 years ago

I don't know why it doesn't work maybe I'm doing something wrong but anyways. Thank you so much.

RebeccaStevens commented 3 years ago

https://runkit.com/rebeccastevens/607bfe1bcbf2a5001a61822b