Merging two %Objects (2016.1/2016.2)

I'm revisiting some older projects that can benefit from the new JSON support and dynamic object capabilities in 2016.1 FT / 2016.2 FT. (Particularly, some of the really new features in the latest 2016.2 FT.)
For the particular thing I'm working on, it would be very handy to be able to merge objects, similarly to https://api.jquery.com/jquery.extend/. The closest thing I've found so far (in 2016.2 only) is:

Set o1 = {"a":1,"c":2}, o2 = {"b":1,"c":1}
Write "o1: ",o1.$toJSON(),!
Write "o2: ",o2.$toJSON(),!
Write !
Write "Merge two objects into a third (new) object, with values from o2 overwriting those from o1 when property names are shared: ",!
Set o3 = o2.$compose({"returnValue":o1.$clone()})
Write "o3: ",o3.$toJSON(),!
Write "o1: ",o1.$toJSON(),!
Write "o2: ",o2.$toJSON(),!
Write !
Write "Merge o2 to o1, overwriting the contents of o1: ",!
Do o2.$compose({"returnValue":o1})
Write "o1: ",o1.$toJSON(),!
Write "o2: ",o2.$toJSON(),!

Which produces the following output:

o1: {"a":1,"c":2}
o2: {"b":1,"c":1}
Merge two objects into a third (new) object, with values from o2 overwriting those from o1 when property names are shared:
o3: {"a":1,"c":1,"b":1}
o1: {"a":1,"c":2}
o2: {"b":1,"c":1}
Merge o2 to o1, overwriting the contents of o1:
o1: {"a":1,"c":1,"b":1}
o2: {"b":1,"c":1}

However, this won't do a "deep" merge; the following code:

Set o1 = {"a":[1,2,3,4],"b":{"c":1,"d":2}}
Set o2 = {"a":[5,6,7,8],"b":{"a":42,"b":2,"c":15}}
Set o3 = o2.$compose({"returnValue":o1.$clone()})
Write o3.$toJSON(),!

Produces this output:

{"a":[5,6,7,8],"b":{"a":42,"b":2,"c":15}}

Any thoughts on the best way to do this? Is there already a "merge" feature?

  • 0
  • 0
  • 272
  • 1
  • 0

Comments

Hi Tim,

$compose works with deep structures but it replaces values of key-value pairs at the top level. It does not merge sub-arrays or sub-objects by default. Consider the following code:

SAMPLES>set o1 = {"a":1,"c":2,"deep":{"f":1,"g":1}}
 
SAMPLES>set o2 = {"b":1,"c":1,"deep":{"f":3,"j":1}}
 
SAMPLES>s o3 = o2.$compose({"returnValue":o1})
 
SAMPLES>w o3.$toJSON()
{"a":1,"c":1,"deep":{"f":3,"j":1},"b":1

You can easily spot, that the path "deep" in o3 has the value from o2 and completely misses "deep.g" from o1. We just copied the path "deep" from o2 into o1. We do provide a way  to override this behavior if you want to, but in a future release, we plan to ease this by introducing compose maps. I will cover this topic in more detail in an upcoming post.