Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

deep-object-merge ? #73

Open
Filipeue opened this issue Feb 15, 2022 · 13 comments
Open

deep-object-merge ? #73

Filipeue opened this issue Feb 15, 2022 · 13 comments

Comments

@Filipeue
Copy link

const originalObject = {...}
const newObject = {...}
const diffObject = deep-object-diff.diff(originalObject, newObject)

Is there a suggested solution how to get new object merging original object with diff object created with deep-object-diff?


I intend to store original object + diff, so later I can merge those two to get new object. Then I compare original with new object using some other lib and render diff on a page.

@mattphillips
Copy link
Owner

Hi @Filipeue I'm not sure I'm following exactly but if you were to take the difference of two objects (lhs and rhs) and merge the diff to the lhs object - would you not just end up with the rhs object?

@Filipeue
Copy link
Author

Filipeue commented Feb 16, 2022

@mattphillips yeah that's exactly what I am trying to achieve
so do you have a suggestion how to merge lhs with diff to get rhs object?

@mattphillips
Copy link
Owner

Sorry if I'm missing something but could you not store the newObject rather than computing the diff to then recompute the new?

I'm not sure what value deep-object-merge would have if it gives the newObject that was used to compute the diff - you'd already have the newObject

@Filipeue
Copy link
Author

Filipeue commented Feb 16, 2022

@mattphillips
This issue is really just a question whether there is something like deep-object-merge function.

But as you are interested in the actual problem I am trying to solve:
Imagine you have to implement history of edits to an entity. Then on the client you want to show what changed from v1 -> v2, or from v2 -> v3 and so on. I already have an implementation where I take left and right object and render only the differences nicely. But to show the formatted diff I need left and right object. Entity can be pretty big so my intention is not to store whole left (v1) object and right (v2) object, but to store left object + diff. Then on the client I would take left object + diff to generate right object and now I have both objects so I can render formatted diff between the objects (specified entity versions) using my existing solution.

These questions may come up:

  • Why won't you just store the diff? And to that I would answer I want to see changes between v2 - v3 of the entity and I have no idea how the entity looked in v2 because now it is for example v9.
  • Why won't you store the diff data or formatted diff you intend to show on client? - I don't want my API to be tied to specific custom diff format. Later I may switch my diff formatter to other lib.

Repository owner deleted a comment from sadeqush Sep 18, 2022
@GabrielCTroia
Copy link

GabrielCTroia commented Feb 17, 2023

Hey @mattphillips did you find a solution to this? I'm looking for a similar way to merge the left object with the diff and get the right object back, sometime after the initial diff was generated :)

@AadamZ5
Copy link

AadamZ5 commented Feb 26, 2023

If you need to track changes on JSON data, consider the JSON Patch mechanism. I started to use this for history edits, only storing the patches and using this lib to apply / revert changes to the data :)

@lmaccherone
Copy link

Is this a duplicate of #71 ?

@GottZ
Copy link

GottZ commented Aug 7, 2023

Sorry if I'm missing something but could you not store the newObject rather than computing the diff to then recompute the new?

I'm not sure what value deep-object-merge would have if it gives the newObject that was used to compute the diff - you'd already have the newObject

imagine the original is a really big dynamically created json object.
now imagine you apply changes to it many times a second.
now imagine you have a second machine somewhere in the internet that would like to have the current state of this object but might be bandwidth constrained..
now to further ramp down the bandwidth requirement, you might even want to only update data every n seconds..

now the target device is ready to receive a new state.. it could tell the source: "ey.. I am at version X, now gimme the diff to the current version"
the server knows said json version, applies a diff, sends it off to the target, the target could patch the diff to it's last state and voila.. it has the new state without much bandwidth usage.

obviously for this, the last sent state must be known to both locations but that's trivial.

I hope this clears up what OP wanted to ask about.

@lmaccherone already posted a nice little solution to this that works really well as following:

// you receive a new state.. so you save the last processed state as old state
oldState = state;
// then you json parse the incoming new state, that was generated on the other end as following:
// JSON.stringify(diff(oldState, state))
// then you apply the diff to the old state:
state = applyDiff(oldState, JSON.parse(text));

voila, state is now equal to upstream without sending the whole json down the wire..

@lmaccherone
Copy link

Nice explanation @GottZ and thanks for the shout out!

I ended up publishing this as its own npm package: https://www.npmjs.com/package/@transformation-dev/deep-object-diff-apply.

@GottZ
Copy link

GottZ commented Aug 8, 2023

already using it in production for a custom monitoring solution since yesterday ;)

bit OT:
data source is in a DMZ and all I got is a HTTP proxy to shove the data through, since I don't intend to put the visual monitoring device into the DMZ for reasons.
(not using https cause they re-issue MITM ssl certs, making it untrustable)

So.. I'm diffing the monitoring state, wrap this in a e2e openpgp message, and send it off to a external device, that then patches it back together and shows a custom monitoring for some DMZ resources..
this in itself already was painful enough to implement.
positive outcome since it doesn't sit in DMZ: I can get phone notifications if something is down now AND this can display just fine on a 4k tv without using citrix in-between.

@GottZ
Copy link

GottZ commented Aug 9, 2023

hm. the diffs are not really serializable and deserializable with JSON.parse and stringify without custom logic.
I got to find / make a proper serialization solution for this use-case then.
(for example, you can't really serialize / deserialized undefined)

@lmaccherone
Copy link

If you want something simple and lightweight, I can recommend @ungap/structured-clone. However, if you want fast and based upon an international standard, there is cbor-x with the structured cloning extension.

Either one of those handles undefined as well as all but a few JavaScript types.

@GottZ
Copy link

GottZ commented Aug 10, 2023

I was already thinking about switching to bson, protobuf or a custom hacky (time budgeted) de/serializer but this is nice indeed!
thanks.
I like lightweight stuff that just get's stuff done.

edit:
ohsnap.. structured clone is already in the node versions I use..
I should follow up on js spec changes more again.. this is gold.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants