diff --git a/core/mapping/jsonunmarshaler_test.go b/core/mapping/jsonunmarshaler_test.go index 4d0de4d16..ac7e7b14c 100644 --- a/core/mapping/jsonunmarshaler_test.go +++ b/core/mapping/jsonunmarshaler_test.go @@ -931,6 +931,113 @@ func TestUnmarshalJsonArray(t *testing.T) { assert.Equal(t, 18, v[0].Age) } +func TestUnmarshalJsonBytesPointerSliceUint64(t *testing.T) { + t.Run("with values", func(t *testing.T) { + var c struct { + IDs *[]uint64 `json:"ids,optional"` + } + content := []byte(`{"ids":[9000,9001]}`) + + assert.Nil(t, UnmarshalJsonBytes(content, &c)) + assert.NotNil(t, c.IDs) + assert.Equal(t, []uint64{9000, 9001}, *c.IDs) + }) + + t.Run("omitted", func(t *testing.T) { + var c struct { + IDs *[]uint64 `json:"ids,optional"` + } + content := []byte(`{}`) + + assert.Nil(t, UnmarshalJsonBytes(content, &c)) + assert.Nil(t, c.IDs) + }) + + t.Run("null", func(t *testing.T) { + var c struct { + IDs *[]uint64 `json:"ids,optional"` + } + content := []byte(`{"ids":null}`) + + assert.Nil(t, UnmarshalJsonBytes(content, &c)) + assert.Nil(t, c.IDs) + }) + + t.Run("empty array", func(t *testing.T) { + var c struct { + IDs *[]uint64 `json:"ids,optional"` + } + content := []byte(`{"ids":[]}`) + + assert.Nil(t, UnmarshalJsonBytes(content, &c)) + assert.NotNil(t, c.IDs) + assert.Equal(t, []uint64{}, *c.IDs) + }) +} + +func TestUnmarshalJsonBytesPointerSliceOtherTypes(t *testing.T) { + t.Run("pointer to []string", func(t *testing.T) { + var c struct { + Names *[]string `json:"names,optional"` + } + content := []byte(`{"names":["a","b"]}`) + + assert.Nil(t, UnmarshalJsonBytes(content, &c)) + assert.NotNil(t, c.Names) + assert.Equal(t, []string{"a", "b"}, *c.Names) + }) + + t.Run("pointer to []int", func(t *testing.T) { + var c struct { + Values *[]int `json:"values,optional"` + } + content := []byte(`{"values":[1,2,3]}`) + + assert.Nil(t, UnmarshalJsonBytes(content, &c)) + assert.NotNil(t, c.Values) + assert.Equal(t, []int{1, 2, 3}, *c.Values) + }) +} + +func TestUnmarshalJsonBytesPointerSliceStruct(t *testing.T) { + type Item struct { + Name string `json:"name"` + Age int `json:"age"` + } + + t.Run("with values", func(t *testing.T) { + var c struct { + Items *[]Item `json:"items,optional"` + } + content := []byte(`{"items":[{"name":"alice","age":30},{"name":"bob","age":25}]}`) + + assert.Nil(t, UnmarshalJsonBytes(content, &c)) + assert.NotNil(t, c.Items) + assert.Equal(t, []Item{{Name: "alice", Age: 30}, {Name: "bob", Age: 25}}, *c.Items) + }) + + t.Run("omitted", func(t *testing.T) { + var c struct { + Items *[]Item `json:"items,optional"` + } + content := []byte(`{}`) + + assert.Nil(t, UnmarshalJsonBytes(content, &c)) + assert.Nil(t, c.Items) + }) + + t.Run("empty array", func(t *testing.T) { + var c struct { + Items *[]Item `json:"items,optional"` + } + content := []byte(`{"items":[]}`) + + assert.Nil(t, UnmarshalJsonBytes(content, &c)) + assert.NotNil(t, c.Items) + assert.Equal(t, []Item{}, *c.Items) + }) +} + func TestUnmarshalJsonBytesError(t *testing.T) { var v []struct { Name string `json:"name"` diff --git a/core/mapping/unmarshaler.go b/core/mapping/unmarshaler.go index d6d73e9d2..fe795aa41 100644 --- a/core/mapping/unmarshaler.go +++ b/core/mapping/unmarshaler.go @@ -142,11 +142,11 @@ func (u *Unmarshaler) fillSlice(fieldType reflect.Type, value reflect.Value, return nil } - baseType := fieldType.Elem() + baseType := Deref(fieldType).Elem() dereffedBaseType := Deref(baseType) dereffedBaseKind := dereffedBaseType.Kind() if refValue.Len() == 0 { - value.Set(reflect.MakeSlice(reflect.SliceOf(baseType), 0, 0)) + SetValue(fieldType, value, reflect.MakeSlice(reflect.SliceOf(baseType), 0, 0)) return nil } @@ -179,7 +179,7 @@ func (u *Unmarshaler) fillSlice(fieldType reflect.Type, value reflect.Value, } if valid { - value.Set(conv) + SetValue(fieldType, value, conv) } return nil @@ -201,7 +201,7 @@ func (u *Unmarshaler) fillSliceFromString(fieldType reflect.Type, value reflect. return errUnsupportedType } - baseFieldType := fieldType.Elem() + baseFieldType := Deref(fieldType).Elem() baseFieldKind := baseFieldType.Kind() conv := reflect.MakeSlice(reflect.SliceOf(baseFieldType), len(slice), cap(slice)) @@ -211,7 +211,7 @@ func (u *Unmarshaler) fillSliceFromString(fieldType reflect.Type, value reflect. } } - value.Set(conv) + SetValue(fieldType, value, conv) return nil }