Skip to content

Commit

Permalink
chore: improve null merging behaviour
Browse files Browse the repository at this point in the history
  • Loading branch information
jensneuse committed Jan 6, 2025
1 parent 534f686 commit 4f910b6
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 25 deletions.
12 changes: 7 additions & 5 deletions mergevalues.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,17 @@ func MergeValues(a, b *Value) (v *Value, changed bool, err error) {
if b == nil {
return a, false, nil
}
if b.Type() == TypeNull && a.Type() == TypeObject {
// we assume that null was returned in an error case for resolving a nested object field
// as we've got an object on the left side, we don't override the whole object with null
// instead, we keep the left object and discard the null on the right side
return a, false, nil
}
aBool, bBool := a.Type() == TypeTrue || a.Type() == TypeFalse, b.Type() == TypeTrue || b.Type() == TypeFalse
booleans := aBool && bBool
oneIsNull := a.Type() == TypeNull || b.Type() == TypeNull
if a.Type() != b.Type() && !booleans && !oneIsNull {
if a.Type() != b.Type() && !booleans {
return nil, false, ErrMergeDifferentTypes
}
if b.Type() == TypeNull && a.Type() != TypeNull {
return b, true, nil
}
switch a.Type() {
case TypeObject:
ao, _ := a.Object()
Expand Down
45 changes: 25 additions & 20 deletions mergevalues_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,20 +183,14 @@ func TestMergeValues(t *testing.T) {
t.Run("null not null", func(t *testing.T) {
t.Parallel()
a, b := MustParse(`null`), MustParse(`1`)
merged, changed, err := MergeValues(a, b)
require.NoError(t, err)
require.Equal(t, true, changed)
out := merged.MarshalTo(nil)
require.Equal(t, `1`, string(out))
_, _, err := MergeValues(a, b)
require.Error(t, err)
})
t.Run("null not null reverse", func(t *testing.T) {
t.Parallel()
a, b := MustParse(`1`), MustParse(`null`)
merged, changed, err := MergeValues(a, b)
require.NoError(t, err)
require.Equal(t, true, changed)
out := merged.MarshalTo(nil)
require.Equal(t, `null`, string(out))
_, _, err := MergeValues(a, b)
require.Error(t, err)
})
t.Run("array objects", func(t *testing.T) {
t.Parallel()
Expand Down Expand Up @@ -272,32 +266,43 @@ func TestMergeValues(t *testing.T) {
t.Parallel()
left := MustParse(`null`)
right := MustParse(`true`)
out, _, err := MergeValues(left, right)
require.NoError(t, err)
require.Equal(t, `true`, out.String())
_, _, err := MergeValues(left, right)
require.Error(t, err)
})
t.Run("true null", func(t *testing.T) {
t.Parallel()
left := MustParse(`true`)
right := MustParse(`null`)
out, _, err := MergeValues(left, right)
require.NoError(t, err)
require.Equal(t, `null`, out.String())
_, _, err := MergeValues(left, right)
require.Error(t, err)
})
t.Run("nested null true", func(t *testing.T) {
t.Parallel()
left := MustParse(`{"a":null}`)
right := MustParse(`{"a":true}`)
out, _, err := MergeValues(left, right)
require.NoError(t, err)
require.Equal(t, `{"a":true}`, out.String())
_, _, err := MergeValues(left, right)
require.Error(t, err)
})
t.Run("nested true null", func(t *testing.T) {
t.Parallel()
left := MustParse(`{"a":true}`)
right := MustParse(`{"a":null}`)
_, _, err := MergeValues(left, right)
require.Error(t, err)
})
t.Run("nested null into nested object", func(t *testing.T) {
t.Parallel()
left := MustParse(`{"a":{"b":"c"}}`)
right := MustParse(`{"a":null}`)
out, _, err := MergeValues(left, right)
require.NoError(t, err)
require.Equal(t, `{"a":null}`, out.String())
require.Equal(t, `{"a":{"b":"c"}}`, out.String())
})
t.Run("nested object into nested null", func(t *testing.T) {
t.Parallel()
left := MustParse(`{"a":null}`)
right := MustParse(`{"a":{"b":"c"}}`)
_, _, err := MergeValues(left, right)
require.Error(t, err)
})
}

0 comments on commit 4f910b6

Please sign in to comment.