Skip to content

Commit 10a1c0a

Browse files
author
Max Goncharenko
committed
MergeMergePatches preserve nulls in complex objects
Signed-off-by: Max Goncharenko <[email protected]>
1 parent 60af5a5 commit 10a1c0a

File tree

4 files changed

+33
-16
lines changed

4 files changed

+33
-16
lines changed

merge.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,10 @@ func mergeDocs(doc, patch *partialDoc, mergeMerge bool) {
3838
cur, ok := (*doc)[k]
3939

4040
if !ok || cur == nil {
41-
pruneNulls(v)
41+
if !mergeMerge {
42+
pruneNulls(v)
43+
}
44+
4245
(*doc)[k] = v
4346
} else {
4447
(*doc)[k] = merge(cur, v, mergeMerge)

merge_test.go

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,7 @@ func createNestedMap(m map[string]interface{}, depth int, objectCount *int) {
454454
if depth == 0 {
455455
return
456456
}
457-
for i := 0; i< 2;i++ {
457+
for i := 0; i < 2; i++ {
458458
nested := map[string]interface{}{}
459459
*objectCount += 1
460460
createNestedMap(nested, depth-1, objectCount)
@@ -546,12 +546,12 @@ func benchmarkMatchesValueWithDeeplyNestedFields(depth int, b *testing.B) {
546546
func BenchmarkMatchesValue1(b *testing.B) { benchmarkMatchesValueWithDeeplyNestedFields(1, b) }
547547
func BenchmarkMatchesValue2(b *testing.B) { benchmarkMatchesValueWithDeeplyNestedFields(2, b) }
548548
func BenchmarkMatchesValue3(b *testing.B) { benchmarkMatchesValueWithDeeplyNestedFields(3, b) }
549-
func BenchmarkMatchesValue4(b *testing.B) { benchmarkMatchesValueWithDeeplyNestedFields(4, b) }
550-
func BenchmarkMatchesValue5(b *testing.B) { benchmarkMatchesValueWithDeeplyNestedFields(5, b) }
551-
func BenchmarkMatchesValue6(b *testing.B) { benchmarkMatchesValueWithDeeplyNestedFields(6, b) }
552-
func BenchmarkMatchesValue7(b *testing.B) { benchmarkMatchesValueWithDeeplyNestedFields(7, b) }
553-
func BenchmarkMatchesValue8(b *testing.B) { benchmarkMatchesValueWithDeeplyNestedFields(8, b) }
554-
func BenchmarkMatchesValue9(b *testing.B) { benchmarkMatchesValueWithDeeplyNestedFields(9, b) }
549+
func BenchmarkMatchesValue4(b *testing.B) { benchmarkMatchesValueWithDeeplyNestedFields(4, b) }
550+
func BenchmarkMatchesValue5(b *testing.B) { benchmarkMatchesValueWithDeeplyNestedFields(5, b) }
551+
func BenchmarkMatchesValue6(b *testing.B) { benchmarkMatchesValueWithDeeplyNestedFields(6, b) }
552+
func BenchmarkMatchesValue7(b *testing.B) { benchmarkMatchesValueWithDeeplyNestedFields(7, b) }
553+
func BenchmarkMatchesValue8(b *testing.B) { benchmarkMatchesValueWithDeeplyNestedFields(8, b) }
554+
func BenchmarkMatchesValue9(b *testing.B) { benchmarkMatchesValueWithDeeplyNestedFields(9, b) }
555555
func BenchmarkMatchesValue10(b *testing.B) { benchmarkMatchesValueWithDeeplyNestedFields(10, b) }
556556

557557
func TestCreateMergePatchComplexRemoveAll(t *testing.T) {
@@ -649,6 +649,12 @@ func TestMergeMergePatches(t *testing.T) {
649649
p2: `{"del2": null}`,
650650
exp: `{"del1": null, "del2": null}`,
651651
},
652+
{
653+
demonstrates: "nulls are kept in complex objects",
654+
p1: `{}`,
655+
p2: `{"request":{"object":{"complex_object_array":["value1","value2","value3"],"complex_object_map":{"key1":"value1","key2":"value2","key3":"value3"},"simple_object_bool":false,"simple_object_float":-5.5,"simple_object_int":5,"simple_object_null":null,"simple_object_string":"example"}}}`,
656+
exp: `{"request":{"object":{"complex_object_array":["value1","value2","value3"],"complex_object_map":{"key1":"value1","key2":"value2","key3":"value3"},"simple_object_bool":false,"simple_object_float":-5.5,"simple_object_int":5,"simple_object_null":null,"simple_object_string":"example"}}}`,
657+
},
652658
{
653659
demonstrates: "a key added then deleted is kept deleted",
654660
p1: `{"add_then_delete": "atd"}`,

v5/merge.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,9 @@ func mergeDocs(doc, patch *partialDoc, mergeMerge bool) {
4848
cur, ok := doc.obj[k]
4949

5050
if !ok || cur == nil {
51-
pruneNulls(v)
51+
if !mergeMerge {
52+
pruneNulls(v)
53+
}
5254
_ = doc.set(k, v, &ApplyOptions{})
5355
} else {
5456
_ = doc.set(k, merge(cur, v, mergeMerge), &ApplyOptions{})

v5/merge_test.go

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,7 @@ func createNestedMap(m map[string]interface{}, depth int, objectCount *int) {
454454
if depth == 0 {
455455
return
456456
}
457-
for i := 0; i< 2;i++ {
457+
for i := 0; i < 2; i++ {
458458
nested := map[string]interface{}{}
459459
*objectCount += 1
460460
createNestedMap(nested, depth-1, objectCount)
@@ -546,12 +546,12 @@ func benchmarkMatchesValueWithDeeplyNestedFields(depth int, b *testing.B) {
546546
func BenchmarkMatchesValue1(b *testing.B) { benchmarkMatchesValueWithDeeplyNestedFields(1, b) }
547547
func BenchmarkMatchesValue2(b *testing.B) { benchmarkMatchesValueWithDeeplyNestedFields(2, b) }
548548
func BenchmarkMatchesValue3(b *testing.B) { benchmarkMatchesValueWithDeeplyNestedFields(3, b) }
549-
func BenchmarkMatchesValue4(b *testing.B) { benchmarkMatchesValueWithDeeplyNestedFields(4, b) }
550-
func BenchmarkMatchesValue5(b *testing.B) { benchmarkMatchesValueWithDeeplyNestedFields(5, b) }
551-
func BenchmarkMatchesValue6(b *testing.B) { benchmarkMatchesValueWithDeeplyNestedFields(6, b) }
552-
func BenchmarkMatchesValue7(b *testing.B) { benchmarkMatchesValueWithDeeplyNestedFields(7, b) }
553-
func BenchmarkMatchesValue8(b *testing.B) { benchmarkMatchesValueWithDeeplyNestedFields(8, b) }
554-
func BenchmarkMatchesValue9(b *testing.B) { benchmarkMatchesValueWithDeeplyNestedFields(9, b) }
549+
func BenchmarkMatchesValue4(b *testing.B) { benchmarkMatchesValueWithDeeplyNestedFields(4, b) }
550+
func BenchmarkMatchesValue5(b *testing.B) { benchmarkMatchesValueWithDeeplyNestedFields(5, b) }
551+
func BenchmarkMatchesValue6(b *testing.B) { benchmarkMatchesValueWithDeeplyNestedFields(6, b) }
552+
func BenchmarkMatchesValue7(b *testing.B) { benchmarkMatchesValueWithDeeplyNestedFields(7, b) }
553+
func BenchmarkMatchesValue8(b *testing.B) { benchmarkMatchesValueWithDeeplyNestedFields(8, b) }
554+
func BenchmarkMatchesValue9(b *testing.B) { benchmarkMatchesValueWithDeeplyNestedFields(9, b) }
555555
func BenchmarkMatchesValue10(b *testing.B) { benchmarkMatchesValueWithDeeplyNestedFields(10, b) }
556556

557557
func TestCreateMergePatchComplexRemoveAll(t *testing.T) {
@@ -649,6 +649,12 @@ func TestMergeMergePatches(t *testing.T) {
649649
p2: `{"del2": null}`,
650650
exp: `{"del1": null, "del2": null}`,
651651
},
652+
{
653+
demonstrates: "nulls are kept in complex objects",
654+
p1: `{}`,
655+
p2: `{"request":{"object":{"complex_object_array":["value1","value2","value3"],"complex_object_map":{"key1":"value1","key2":"value2","key3":"value3"},"simple_object_bool":false,"simple_object_float":-5.5,"simple_object_int":5,"simple_object_null":null,"simple_object_string":"example"}}}`,
656+
exp: `{"request":{"object":{"complex_object_array":["value1","value2","value3"],"complex_object_map":{"key1":"value1","key2":"value2","key3":"value3"},"simple_object_bool":false,"simple_object_float":-5.5,"simple_object_int":5,"simple_object_null":null,"simple_object_string":"example"}}}`,
657+
},
652658
{
653659
demonstrates: "a key added then deleted is kept deleted",
654660
p1: `{"add_then_delete": "atd"}`,

0 commit comments

Comments
 (0)