|
|
|
@ -306,30 +306,61 @@ func TestUnmarshalIntPtr(t *testing.T) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestUnmarshalIntSliceOfPtr(t *testing.T) {
|
|
|
|
|
type inner struct {
|
|
|
|
|
Ints []*int `key:"ints"`
|
|
|
|
|
Intps []**int `key:"intps"`
|
|
|
|
|
}
|
|
|
|
|
m := map[string]any{
|
|
|
|
|
"ints": []int{1, 2, 3},
|
|
|
|
|
"intps": []int{1, 2, 3, 4},
|
|
|
|
|
}
|
|
|
|
|
t.Run("int slice", func(t *testing.T) {
|
|
|
|
|
type inner struct {
|
|
|
|
|
Ints []*int `key:"ints"`
|
|
|
|
|
Intps []**int `key:"intps"`
|
|
|
|
|
}
|
|
|
|
|
m := map[string]any{
|
|
|
|
|
"ints": []int{1, 2, 3},
|
|
|
|
|
"intps": []int{1, 2, 3, 4},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var in inner
|
|
|
|
|
if assert.NoError(t, UnmarshalKey(m, &in)) {
|
|
|
|
|
assert.NotEmpty(t, in.Ints)
|
|
|
|
|
var ints []int
|
|
|
|
|
for _, i := range in.Ints {
|
|
|
|
|
ints = append(ints, *i)
|
|
|
|
|
var in inner
|
|
|
|
|
if assert.NoError(t, UnmarshalKey(m, &in)) {
|
|
|
|
|
assert.NotEmpty(t, in.Ints)
|
|
|
|
|
var ints []int
|
|
|
|
|
for _, i := range in.Ints {
|
|
|
|
|
ints = append(ints, *i)
|
|
|
|
|
}
|
|
|
|
|
assert.EqualValues(t, []int{1, 2, 3}, ints)
|
|
|
|
|
|
|
|
|
|
var intps []int
|
|
|
|
|
for _, i := range in.Intps {
|
|
|
|
|
intps = append(intps, **i)
|
|
|
|
|
}
|
|
|
|
|
assert.EqualValues(t, []int{1, 2, 3, 4}, intps)
|
|
|
|
|
}
|
|
|
|
|
assert.EqualValues(t, []int{1, 2, 3}, ints)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
var intps []int
|
|
|
|
|
for _, i := range in.Intps {
|
|
|
|
|
intps = append(intps, **i)
|
|
|
|
|
t.Run("int slice with error", func(t *testing.T) {
|
|
|
|
|
type inner struct {
|
|
|
|
|
Ints []*int `key:"ints"`
|
|
|
|
|
Intps []**int `key:"intps"`
|
|
|
|
|
}
|
|
|
|
|
assert.EqualValues(t, []int{1, 2, 3, 4}, intps)
|
|
|
|
|
}
|
|
|
|
|
m := map[string]any{
|
|
|
|
|
"ints": []any{1, 2, "a"},
|
|
|
|
|
"intps": []int{1, 2, 3, 4},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var in inner
|
|
|
|
|
assert.Error(t, UnmarshalKey(m, &in))
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("int slice with nil", func(t *testing.T) {
|
|
|
|
|
type inner struct {
|
|
|
|
|
Ints []int `key:"ints"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m := map[string]any{
|
|
|
|
|
"ints": []any{nil},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var in inner
|
|
|
|
|
if assert.NoError(t, UnmarshalKey(m, &in)) {
|
|
|
|
|
assert.Empty(t, in.Ints)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestUnmarshalIntWithDefault(t *testing.T) {
|
|
|
|
@ -373,6 +404,42 @@ func TestUnmarshalIntWithString(t *testing.T) {
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("int wrong range", func(t *testing.T) {
|
|
|
|
|
type inner struct {
|
|
|
|
|
Int int64 `key:"int,string,range=[2:3]"`
|
|
|
|
|
Intp *int64 `key:"intp,range=[2:3]"`
|
|
|
|
|
Intpp **int64 `key:"intpp,range=[2:3]"`
|
|
|
|
|
}
|
|
|
|
|
m := map[string]any{
|
|
|
|
|
"int": json.Number("1"),
|
|
|
|
|
"intp": json.Number("2"),
|
|
|
|
|
"intpp": json.Number("3"),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var in inner
|
|
|
|
|
assert.ErrorIs(t, UnmarshalKey(m, &in), errNumberRange)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("int with wrong type", func(t *testing.T) {
|
|
|
|
|
type (
|
|
|
|
|
myString string
|
|
|
|
|
|
|
|
|
|
inner struct {
|
|
|
|
|
Int int64 `key:"int,string"`
|
|
|
|
|
Intp *int64 `key:"intp,string"`
|
|
|
|
|
Intpp **int64 `key:"intpp,string"`
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
m := map[string]any{
|
|
|
|
|
"int": myString("1"),
|
|
|
|
|
"intp": myString("2"),
|
|
|
|
|
"intpp": myString("3"),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var in inner
|
|
|
|
|
assert.Error(t, UnmarshalKey(m, &in))
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("int with ptr", func(t *testing.T) {
|
|
|
|
|
type inner struct {
|
|
|
|
|
Int *int64 `key:"int"`
|
|
|
|
@ -387,6 +454,54 @@ func TestUnmarshalIntWithString(t *testing.T) {
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("int with invalid value", func(t *testing.T) {
|
|
|
|
|
type inner struct {
|
|
|
|
|
Int int64 `key:"int"`
|
|
|
|
|
}
|
|
|
|
|
m := map[string]any{
|
|
|
|
|
"int": json.Number("a"),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var in inner
|
|
|
|
|
assert.Error(t, UnmarshalKey(m, &in))
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("uint with invalid value", func(t *testing.T) {
|
|
|
|
|
type inner struct {
|
|
|
|
|
Int uint64 `key:"int"`
|
|
|
|
|
}
|
|
|
|
|
m := map[string]any{
|
|
|
|
|
"int": json.Number("a"),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var in inner
|
|
|
|
|
assert.Error(t, UnmarshalKey(m, &in))
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("float with invalid value", func(t *testing.T) {
|
|
|
|
|
type inner struct {
|
|
|
|
|
Value float64 `key:"float"`
|
|
|
|
|
}
|
|
|
|
|
m := map[string]any{
|
|
|
|
|
"float": json.Number("a"),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var in inner
|
|
|
|
|
assert.Error(t, UnmarshalKey(m, &in))
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("float with invalid value", func(t *testing.T) {
|
|
|
|
|
type inner struct {
|
|
|
|
|
Value string `key:"value"`
|
|
|
|
|
}
|
|
|
|
|
m := map[string]any{
|
|
|
|
|
"value": json.Number("a"),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var in inner
|
|
|
|
|
assert.Error(t, UnmarshalKey(m, &in))
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("int with ptr of ptr", func(t *testing.T) {
|
|
|
|
|
type inner struct {
|
|
|
|
|
Int **int64 `key:"int"`
|
|
|
|
@ -491,14 +606,25 @@ func TestUnmarshalBoolSliceEmpty(t *testing.T) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestUnmarshalBoolSliceWithDefault(t *testing.T) {
|
|
|
|
|
type inner struct {
|
|
|
|
|
Bools []bool `key:"bools,default=[true,false]"`
|
|
|
|
|
}
|
|
|
|
|
t.Run("slice with default", func(t *testing.T) {
|
|
|
|
|
type inner struct {
|
|
|
|
|
Bools []bool `key:"bools,default=[true,false]"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var in inner
|
|
|
|
|
if assert.NoError(t, UnmarshalKey(nil, &in)) {
|
|
|
|
|
assert.ElementsMatch(t, []bool{true, false}, in.Bools)
|
|
|
|
|
}
|
|
|
|
|
var in inner
|
|
|
|
|
if assert.NoError(t, UnmarshalKey(nil, &in)) {
|
|
|
|
|
assert.ElementsMatch(t, []bool{true, false}, in.Bools)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("slice with default error", func(t *testing.T) {
|
|
|
|
|
type inner struct {
|
|
|
|
|
Bools []bool `key:"bools,default=[true,fal]"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var in inner
|
|
|
|
|
assert.Error(t, UnmarshalKey(nil, &in))
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestUnmarshalIntSliceWithDefault(t *testing.T) {
|
|
|
|
@ -726,19 +852,45 @@ func TestUnmarshalStringWithMissing(t *testing.T) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestUnmarshalStringSliceFromString(t *testing.T) {
|
|
|
|
|
var v struct {
|
|
|
|
|
Names []string `key:"names"`
|
|
|
|
|
}
|
|
|
|
|
m := map[string]any{
|
|
|
|
|
"names": `["first", "second"]`,
|
|
|
|
|
}
|
|
|
|
|
t.Run("slice from string", func(t *testing.T) {
|
|
|
|
|
var v struct {
|
|
|
|
|
Names []string `key:"names"`
|
|
|
|
|
}
|
|
|
|
|
m := map[string]any{
|
|
|
|
|
"names": `["first", "second"]`,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ast := assert.New(t)
|
|
|
|
|
if ast.NoError(UnmarshalKey(m, &v)) {
|
|
|
|
|
ast.Equal(2, len(v.Names))
|
|
|
|
|
ast.Equal("first", v.Names[0])
|
|
|
|
|
ast.Equal("second", v.Names[1])
|
|
|
|
|
}
|
|
|
|
|
ast := assert.New(t)
|
|
|
|
|
if ast.NoError(UnmarshalKey(m, &v)) {
|
|
|
|
|
ast.Equal(2, len(v.Names))
|
|
|
|
|
ast.Equal("first", v.Names[0])
|
|
|
|
|
ast.Equal("second", v.Names[1])
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("slice from string with slice error", func(t *testing.T) {
|
|
|
|
|
var v struct {
|
|
|
|
|
Names []int `key:"names"`
|
|
|
|
|
}
|
|
|
|
|
m := map[string]any{
|
|
|
|
|
"names": `["first", 1]`,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assert.Error(t, UnmarshalKey(m, &v))
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("slice from string with error", func(t *testing.T) {
|
|
|
|
|
type myString string
|
|
|
|
|
|
|
|
|
|
var v struct {
|
|
|
|
|
Names []string `key:"names"`
|
|
|
|
|
}
|
|
|
|
|
m := map[string]any{
|
|
|
|
|
"names": myString("not a slice"),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assert.Error(t, UnmarshalKey(m, &v))
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestUnmarshalIntSliceFromString(t *testing.T) {
|
|
|
|
@ -800,19 +952,32 @@ func (c CustomStringer) String() string {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestUnmarshalStringMapFromStringer(t *testing.T) {
|
|
|
|
|
var v struct {
|
|
|
|
|
Sort map[string]string `key:"sort"`
|
|
|
|
|
}
|
|
|
|
|
m := map[string]any{
|
|
|
|
|
"sort": CustomStringer(`"value":"ascend","emptyStr":""`),
|
|
|
|
|
}
|
|
|
|
|
t.Run("CustomStringer", func(t *testing.T) {
|
|
|
|
|
var v struct {
|
|
|
|
|
Sort map[string]string `key:"sort"`
|
|
|
|
|
}
|
|
|
|
|
m := map[string]any{
|
|
|
|
|
"sort": CustomStringer(`"value":"ascend","emptyStr":""`),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ast := assert.New(t)
|
|
|
|
|
if ast.NoError(UnmarshalKey(m, &v)) {
|
|
|
|
|
ast.Equal(2, len(v.Sort))
|
|
|
|
|
ast.Equal("ascend", v.Sort["value"])
|
|
|
|
|
ast.Equal("", v.Sort["emptyStr"])
|
|
|
|
|
}
|
|
|
|
|
ast := assert.New(t)
|
|
|
|
|
if ast.NoError(UnmarshalKey(m, &v)) {
|
|
|
|
|
ast.Equal(2, len(v.Sort))
|
|
|
|
|
ast.Equal("ascend", v.Sort["value"])
|
|
|
|
|
ast.Equal("", v.Sort["emptyStr"])
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("CustomStringer incorrect", func(t *testing.T) {
|
|
|
|
|
var v struct {
|
|
|
|
|
Sort map[string]string `key:"sort"`
|
|
|
|
|
}
|
|
|
|
|
m := map[string]any{
|
|
|
|
|
"sort": CustomStringer(`"value"`),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assert.Error(t, UnmarshalKey(m, &v))
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestUnmarshalStringMapFromUnsupportedType(t *testing.T) {
|
|
|
|
@ -906,48 +1071,83 @@ func TestUnmarshalStringSliceMapFromString(t *testing.T) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestUnmarshalStruct(t *testing.T) {
|
|
|
|
|
type address struct {
|
|
|
|
|
City string `key:"city"`
|
|
|
|
|
ZipCode int `key:"zipcode,string"`
|
|
|
|
|
DefaultString string `key:"defaultstring,default=hello"`
|
|
|
|
|
Optional string `key:",optional"`
|
|
|
|
|
}
|
|
|
|
|
type inner struct {
|
|
|
|
|
Name string `key:"name"`
|
|
|
|
|
Address address `key:"address"`
|
|
|
|
|
AddressP *address `key:"addressp"`
|
|
|
|
|
AddressPP **address `key:"addresspp"`
|
|
|
|
|
}
|
|
|
|
|
m := map[string]any{
|
|
|
|
|
"name": "kevin",
|
|
|
|
|
"address": map[string]any{
|
|
|
|
|
"city": "shanghai",
|
|
|
|
|
"zipcode": "200000",
|
|
|
|
|
},
|
|
|
|
|
"addressp": map[string]any{
|
|
|
|
|
"city": "beijing",
|
|
|
|
|
"zipcode": "300000",
|
|
|
|
|
},
|
|
|
|
|
"addresspp": map[string]any{
|
|
|
|
|
"city": "guangzhou",
|
|
|
|
|
"zipcode": "400000",
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
t.Run("struct", func(t *testing.T) {
|
|
|
|
|
type address struct {
|
|
|
|
|
City string `key:"city"`
|
|
|
|
|
ZipCode int `key:"zipcode,string"`
|
|
|
|
|
DefaultString string `key:"defaultstring,default=hello"`
|
|
|
|
|
Optional string `key:",optional"`
|
|
|
|
|
}
|
|
|
|
|
type inner struct {
|
|
|
|
|
Name string `key:"name"`
|
|
|
|
|
Address address `key:"address"`
|
|
|
|
|
AddressP *address `key:"addressp"`
|
|
|
|
|
AddressPP **address `key:"addresspp"`
|
|
|
|
|
}
|
|
|
|
|
m := map[string]any{
|
|
|
|
|
"name": "kevin",
|
|
|
|
|
"address": map[string]any{
|
|
|
|
|
"city": "shanghai",
|
|
|
|
|
"zipcode": "200000",
|
|
|
|
|
},
|
|
|
|
|
"addressp": map[string]any{
|
|
|
|
|
"city": "beijing",
|
|
|
|
|
"zipcode": "300000",
|
|
|
|
|
},
|
|
|
|
|
"addresspp": map[string]any{
|
|
|
|
|
"city": "guangzhou",
|
|
|
|
|
"zipcode": "400000",
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var in inner
|
|
|
|
|
ast := assert.New(t)
|
|
|
|
|
if ast.NoError(UnmarshalKey(m, &in)) {
|
|
|
|
|
ast.Equal("kevin", in.Name)
|
|
|
|
|
ast.Equal("shanghai", in.Address.City)
|
|
|
|
|
ast.Equal(200000, in.Address.ZipCode)
|
|
|
|
|
ast.Equal("hello", in.AddressP.DefaultString)
|
|
|
|
|
ast.Equal("beijing", in.AddressP.City)
|
|
|
|
|
ast.Equal(300000, in.AddressP.ZipCode)
|
|
|
|
|
ast.Equal("hello", in.AddressP.DefaultString)
|
|
|
|
|
ast.Equal("guangzhou", (*in.AddressPP).City)
|
|
|
|
|
ast.Equal(400000, (*in.AddressPP).ZipCode)
|
|
|
|
|
ast.Equal("hello", (*in.AddressPP).DefaultString)
|
|
|
|
|
}
|
|
|
|
|
var in inner
|
|
|
|
|
ast := assert.New(t)
|
|
|
|
|
if ast.NoError(UnmarshalKey(m, &in)) {
|
|
|
|
|
ast.Equal("kevin", in.Name)
|
|
|
|
|
ast.Equal("shanghai", in.Address.City)
|
|
|
|
|
ast.Equal(200000, in.Address.ZipCode)
|
|
|
|
|
ast.Equal("hello", in.AddressP.DefaultString)
|
|
|
|
|
ast.Equal("beijing", in.AddressP.City)
|
|
|
|
|
ast.Equal(300000, in.AddressP.ZipCode)
|
|
|
|
|
ast.Equal("hello", in.AddressP.DefaultString)
|
|
|
|
|
ast.Equal("guangzhou", (*in.AddressPP).City)
|
|
|
|
|
ast.Equal(400000, (*in.AddressPP).ZipCode)
|
|
|
|
|
ast.Equal("hello", (*in.AddressPP).DefaultString)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("struct with error", func(t *testing.T) {
|
|
|
|
|
type address struct {
|
|
|
|
|
City string `key:"city"`
|
|
|
|
|
ZipCode int `key:"zipcode,string"`
|
|
|
|
|
DefaultString string `key:"defaultstring,default=hello"`
|
|
|
|
|
Optional string `key:",optional"`
|
|
|
|
|
}
|
|
|
|
|
type inner struct {
|
|
|
|
|
Name string `key:"name"`
|
|
|
|
|
Address address `key:"address"`
|
|
|
|
|
AddressP *address `key:"addressp"`
|
|
|
|
|
AddressPP **address `key:"addresspp"`
|
|
|
|
|
}
|
|
|
|
|
m := map[string]any{
|
|
|
|
|
"name": "kevin",
|
|
|
|
|
"address": map[string]any{
|
|
|
|
|
"city": "shanghai",
|
|
|
|
|
"zipcode": "200000",
|
|
|
|
|
},
|
|
|
|
|
"addressp": map[string]any{
|
|
|
|
|
"city": "beijing",
|
|
|
|
|
"zipcode": "300000",
|
|
|
|
|
},
|
|
|
|
|
"addresspp": map[string]any{
|
|
|
|
|
"city": "guangzhou",
|
|
|
|
|
"zipcode": "a",
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var in inner
|
|
|
|
|
assert.Error(t, UnmarshalKey(m, &in))
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestUnmarshalStructOptionalDepends(t *testing.T) {
|
|
|
|
@ -1086,21 +1286,44 @@ func TestUnmarshalStructOptionalDependsNot(t *testing.T) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestUnmarshalStructOptionalDependsNotErrorDetails(t *testing.T) {
|
|
|
|
|
type address struct {
|
|
|
|
|
Optional string `key:",optional"`
|
|
|
|
|
OptionalDepends string `key:",optional=!Optional"`
|
|
|
|
|
}
|
|
|
|
|
type inner struct {
|
|
|
|
|
Name string `key:"name"`
|
|
|
|
|
Address address `key:"address"`
|
|
|
|
|
}
|
|
|
|
|
t.Run("mutal optionals", func(t *testing.T) {
|
|
|
|
|
type address struct {
|
|
|
|
|
Optional string `key:",optional"`
|
|
|
|
|
OptionalDepends string `key:",optional=!Optional"`
|
|
|
|
|
}
|
|
|
|
|
type inner struct {
|
|
|
|
|
Name string `key:"name"`
|
|
|
|
|
Address address `key:"address"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m := map[string]any{
|
|
|
|
|
"name": "kevin",
|
|
|
|
|
}
|
|
|
|
|
m := map[string]any{
|
|
|
|
|
"name": "kevin",
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var in inner
|
|
|
|
|
assert.Error(t, UnmarshalKey(m, &in))
|
|
|
|
|
var in inner
|
|
|
|
|
assert.Error(t, UnmarshalKey(m, &in))
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("with default", func(t *testing.T) {
|
|
|
|
|
type address struct {
|
|
|
|
|
Optional string `key:",optional"`
|
|
|
|
|
OptionalDepends string `key:",default=value,optional"`
|
|
|
|
|
}
|
|
|
|
|
type inner struct {
|
|
|
|
|
Name string `key:"name"`
|
|
|
|
|
Address address `key:"address"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m := map[string]any{
|
|
|
|
|
"name": "kevin",
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var in inner
|
|
|
|
|
if assert.NoError(t, UnmarshalKey(m, &in)) {
|
|
|
|
|
assert.Equal(t, "kevin", in.Name)
|
|
|
|
|
assert.Equal(t, "value", in.Address.OptionalDepends)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestUnmarshalStructOptionalDependsNotNested(t *testing.T) {
|
|
|
|
@ -1440,16 +1663,48 @@ func TestUnmarshalMapOfInt(t *testing.T) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestUnmarshalMapOfStructError(t *testing.T) {
|
|
|
|
|
m := map[string]any{
|
|
|
|
|
"Ids": map[string]any{"first": "second"},
|
|
|
|
|
}
|
|
|
|
|
var v struct {
|
|
|
|
|
Ids map[string]struct {
|
|
|
|
|
Name string
|
|
|
|
|
func TestUnmarshalMapOfStruct(t *testing.T) {
|
|
|
|
|
t.Run("map of struct with error", func(t *testing.T) {
|
|
|
|
|
m := map[string]any{
|
|
|
|
|
"Ids": map[string]any{"first": "second"},
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
assert.Error(t, UnmarshalKey(m, &v))
|
|
|
|
|
var v struct {
|
|
|
|
|
Ids map[string]struct {
|
|
|
|
|
Name string
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
assert.Error(t, UnmarshalKey(m, &v))
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("map of struct", func(t *testing.T) {
|
|
|
|
|
m := map[string]any{
|
|
|
|
|
"Ids": map[string]any{
|
|
|
|
|
"foo": map[string]any{"Name": "foo"},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
var v struct {
|
|
|
|
|
Ids map[string]struct {
|
|
|
|
|
Name string
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if assert.NoError(t, UnmarshalKey(m, &v)) {
|
|
|
|
|
assert.Equal(t, "foo", v.Ids["foo"].Name)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("map of struct error", func(t *testing.T) {
|
|
|
|
|
m := map[string]any{
|
|
|
|
|
"Ids": map[string]any{
|
|
|
|
|
"foo": map[string]any{"name": "foo"},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
var v struct {
|
|
|
|
|
Ids map[string]struct {
|
|
|
|
|
Name string
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
assert.Error(t, UnmarshalKey(m, &v))
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestUnmarshalSlice(t *testing.T) {
|
|
|
|
@ -1492,26 +1747,46 @@ func TestUnmarshalSlice(t *testing.T) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestUnmarshalSliceOfStruct(t *testing.T) {
|
|
|
|
|
m := map[string]any{
|
|
|
|
|
"Ids": []map[string]any{
|
|
|
|
|
{
|
|
|
|
|
"First": 1,
|
|
|
|
|
"Second": 2,
|
|
|
|
|
t.Run("slice of struct", func(t *testing.T) {
|
|
|
|
|
m := map[string]any{
|
|
|
|
|
"Ids": []map[string]any{
|
|
|
|
|
{
|
|
|
|
|
"First": 1,
|
|
|
|
|
"Second": 2,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
var v struct {
|
|
|
|
|
Ids []struct {
|
|
|
|
|
First int
|
|
|
|
|
Second int
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ast := assert.New(t)
|
|
|
|
|
if ast.NoError(UnmarshalKey(m, &v)) {
|
|
|
|
|
ast.Equal(1, len(v.Ids))
|
|
|
|
|
ast.Equal(1, v.Ids[0].First)
|
|
|
|
|
ast.Equal(2, v.Ids[0].Second)
|
|
|
|
|
}
|
|
|
|
|
var v struct {
|
|
|
|
|
Ids []struct {
|
|
|
|
|
First int
|
|
|
|
|
Second int
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ast := assert.New(t)
|
|
|
|
|
if ast.NoError(UnmarshalKey(m, &v)) {
|
|
|
|
|
ast.Equal(1, len(v.Ids))
|
|
|
|
|
ast.Equal(1, v.Ids[0].First)
|
|
|
|
|
ast.Equal(2, v.Ids[0].Second)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("slice of struct", func(t *testing.T) {
|
|
|
|
|
m := map[string]any{
|
|
|
|
|
"Ids": []map[string]any{
|
|
|
|
|
{
|
|
|
|
|
"First": "a",
|
|
|
|
|
"Second": 2,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
var v struct {
|
|
|
|
|
Ids []struct {
|
|
|
|
|
First int
|
|
|
|
|
Second int
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
assert.Error(t, UnmarshalKey(m, &v))
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestUnmarshalWithStringOptionsCorrect(t *testing.T) {
|
|
|
|
@ -3122,21 +3397,57 @@ func TestUnmarshalRangeError(t *testing.T) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestUnmarshalNestedMap(t *testing.T) {
|
|
|
|
|
var c struct {
|
|
|
|
|
Anything map[string]map[string]string `json:"anything"`
|
|
|
|
|
}
|
|
|
|
|
m := map[string]any{
|
|
|
|
|
"anything": map[string]map[string]any{
|
|
|
|
|
"inner": {
|
|
|
|
|
"id": "1",
|
|
|
|
|
"name": "any",
|
|
|
|
|
t.Run("nested map", func(t *testing.T) {
|
|
|
|
|
var c struct {
|
|
|
|
|
Anything map[string]map[string]string `json:"anything"`
|
|
|
|
|
}
|
|
|
|
|
m := map[string]any{
|
|
|
|
|
"anything": map[string]map[string]any{
|
|
|
|
|
"inner": {
|
|
|
|
|
"id": "1",
|
|
|
|
|
"name": "any",
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if assert.NoError(t, NewUnmarshaler("json").Unmarshal(m, &c)) {
|
|
|
|
|
assert.Equal(t, "1", c.Anything["inner"]["id"])
|
|
|
|
|
}
|
|
|
|
|
if assert.NoError(t, NewUnmarshaler("json").Unmarshal(m, &c)) {
|
|
|
|
|
assert.Equal(t, "1", c.Anything["inner"]["id"])
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("nested map with slice element", func(t *testing.T) {
|
|
|
|
|
var c struct {
|
|
|
|
|
Anything map[string][]string `json:"anything"`
|
|
|
|
|
}
|
|
|
|
|
m := map[string]any{
|
|
|
|
|
"anything": map[string][]any{
|
|
|
|
|
"inner": {
|
|
|
|
|
"id",
|
|
|
|
|
"name",
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if assert.NoError(t, NewUnmarshaler("json").Unmarshal(m, &c)) {
|
|
|
|
|
assert.Equal(t, []string{"id", "name"}, c.Anything["inner"])
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("nested map with slice element error", func(t *testing.T) {
|
|
|
|
|
var c struct {
|
|
|
|
|
Anything map[string][]string `json:"anything"`
|
|
|
|
|
}
|
|
|
|
|
m := map[string]any{
|
|
|
|
|
"anything": map[string][]any{
|
|
|
|
|
"inner": {
|
|
|
|
|
"id",
|
|
|
|
|
1,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assert.Error(t, NewUnmarshaler("json").Unmarshal(m, &c))
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestUnmarshalNestedMapMismatch(t *testing.T) {
|
|
|
|
@ -3810,15 +4121,27 @@ func TestUnmarshal_EnvWithOptionsWrongValueString(t *testing.T) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestUnmarshalJsonReaderMultiArray(t *testing.T) {
|
|
|
|
|
var res struct {
|
|
|
|
|
A string `json:"a"`
|
|
|
|
|
B [][]string `json:"b"`
|
|
|
|
|
}
|
|
|
|
|
payload := `{"a": "133", "b": [["add", "cccd"], ["eeee"]]}`
|
|
|
|
|
reader := strings.NewReader(payload)
|
|
|
|
|
if assert.NoError(t, UnmarshalJsonReader(reader, &res)) {
|
|
|
|
|
assert.Equal(t, 2, len(res.B))
|
|
|
|
|
}
|
|
|
|
|
t.Run("reader multi array", func(t *testing.T) {
|
|
|
|
|
var res struct {
|
|
|
|
|
A string `json:"a"`
|
|
|
|
|
B [][]string `json:"b"`
|
|
|
|
|
}
|
|
|
|
|
payload := `{"a": "133", "b": [["add", "cccd"], ["eeee"]]}`
|
|
|
|
|
reader := strings.NewReader(payload)
|
|
|
|
|
if assert.NoError(t, UnmarshalJsonReader(reader, &res)) {
|
|
|
|
|
assert.Equal(t, 2, len(res.B))
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("reader multi array with error", func(t *testing.T) {
|
|
|
|
|
var res struct {
|
|
|
|
|
A string `json:"a"`
|
|
|
|
|
B [][]string `json:"b"`
|
|
|
|
|
}
|
|
|
|
|
payload := `{"a": "133", "b": ["eeee"]}`
|
|
|
|
|
reader := strings.NewReader(payload)
|
|
|
|
|
assert.Error(t, UnmarshalJsonReader(reader, &res))
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestUnmarshalJsonReaderPtrMultiArrayString(t *testing.T) {
|
|
|
|
@ -4059,12 +4382,24 @@ func TestUnmarshalJsonReaderWithTypeMismatchBool(t *testing.T) {
|
|
|
|
|
assert.Equal(t, errTypeMismatch, UnmarshalJsonReader(strings.NewReader(body), &req))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestUnmarshalJsonReaderWithTypeMismatchString(t *testing.T) {
|
|
|
|
|
var req struct {
|
|
|
|
|
Params map[string]string `json:"params"`
|
|
|
|
|
}
|
|
|
|
|
body := `{"params":{"a":{"a":123}}}`
|
|
|
|
|
assert.Equal(t, errTypeMismatch, UnmarshalJsonReader(strings.NewReader(body), &req))
|
|
|
|
|
func TestUnmarshalJsonReaderWithTypeString(t *testing.T) {
|
|
|
|
|
t.Run("string type", func(t *testing.T) {
|
|
|
|
|
var req struct {
|
|
|
|
|
Params map[string]string `json:"params"`
|
|
|
|
|
}
|
|
|
|
|
body := `{"params":{"a":"b"}}`
|
|
|
|
|
if assert.NoError(t, UnmarshalJsonReader(strings.NewReader(body), &req)) {
|
|
|
|
|
assert.Equal(t, "b", req.Params["a"])
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("string type mismatch", func(t *testing.T) {
|
|
|
|
|
var req struct {
|
|
|
|
|
Params map[string]string `json:"params"`
|
|
|
|
|
}
|
|
|
|
|
body := `{"params":{"a":{"a":123}}}`
|
|
|
|
|
assert.Equal(t, errTypeMismatch, UnmarshalJsonReader(strings.NewReader(body), &req))
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestUnmarshalJsonReaderWithMismatchType(t *testing.T) {
|
|
|
|
@ -4077,43 +4412,95 @@ func TestUnmarshalJsonReaderWithMismatchType(t *testing.T) {
|
|
|
|
|
assert.Equal(t, errTypeMismatch, UnmarshalJsonReader(strings.NewReader(body), &req))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestUnmarshalJsonReaderWithMismatchTypeBool(t *testing.T) {
|
|
|
|
|
type Req struct {
|
|
|
|
|
Params map[string]bool `json:"params"`
|
|
|
|
|
}
|
|
|
|
|
func TestUnmarshalJsonReaderWithTypeBool(t *testing.T) {
|
|
|
|
|
t.Run("bool type", func(t *testing.T) {
|
|
|
|
|
type Req struct {
|
|
|
|
|
Params map[string]bool `json:"params"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tests := []struct {
|
|
|
|
|
name string
|
|
|
|
|
input string
|
|
|
|
|
}{
|
|
|
|
|
{
|
|
|
|
|
name: "int",
|
|
|
|
|
input: `{"params":{"a":123}}`,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "int",
|
|
|
|
|
input: `{"params":{"a":"123"}}`,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
tests := []struct {
|
|
|
|
|
name string
|
|
|
|
|
input string
|
|
|
|
|
expect bool
|
|
|
|
|
}{
|
|
|
|
|
{
|
|
|
|
|
name: "int",
|
|
|
|
|
input: `{"params":{"a":1}}`,
|
|
|
|
|
expect: true,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "int",
|
|
|
|
|
input: `{"params":{"a":0}}`,
|
|
|
|
|
expect: false,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, test := range tests {
|
|
|
|
|
test := test
|
|
|
|
|
t.Run(test.name, func(t *testing.T) {
|
|
|
|
|
var req Req
|
|
|
|
|
assert.Equal(t, errTypeMismatch, UnmarshalJsonReader(strings.NewReader(test.input), &req))
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
for _, test := range tests {
|
|
|
|
|
test := test
|
|
|
|
|
t.Run(test.name, func(t *testing.T) {
|
|
|
|
|
var req Req
|
|
|
|
|
if assert.NoError(t, UnmarshalJsonReader(strings.NewReader(test.input), &req)) {
|
|
|
|
|
assert.Equal(t, test.expect, req.Params["a"])
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("bool type mismatch", func(t *testing.T) {
|
|
|
|
|
type Req struct {
|
|
|
|
|
Params map[string]bool `json:"params"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tests := []struct {
|
|
|
|
|
name string
|
|
|
|
|
input string
|
|
|
|
|
}{
|
|
|
|
|
{
|
|
|
|
|
name: "int",
|
|
|
|
|
input: `{"params":{"a":123}}`,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "int",
|
|
|
|
|
input: `{"params":{"a":"123"}}`,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, test := range tests {
|
|
|
|
|
test := test
|
|
|
|
|
t.Run(test.name, func(t *testing.T) {
|
|
|
|
|
var req Req
|
|
|
|
|
assert.Equal(t, errTypeMismatch, UnmarshalJsonReader(strings.NewReader(test.input), &req))
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestUnmarshalJsonReaderWithMismatchTypeBoolMap(t *testing.T) {
|
|
|
|
|
var req struct {
|
|
|
|
|
Params map[string]string `json:"params"`
|
|
|
|
|
}
|
|
|
|
|
assert.Equal(t, errTypeMismatch, UnmarshalJsonMap(map[string]any{
|
|
|
|
|
"params": map[string]any{
|
|
|
|
|
"a": true,
|
|
|
|
|
},
|
|
|
|
|
}, &req))
|
|
|
|
|
func TestUnmarshalJsonReaderWithTypeBoolMap(t *testing.T) {
|
|
|
|
|
t.Run("bool map", func(t *testing.T) {
|
|
|
|
|
var req struct {
|
|
|
|
|
Params map[string]bool `json:"params"`
|
|
|
|
|
}
|
|
|
|
|
if assert.NoError(t, UnmarshalJsonMap(map[string]any{
|
|
|
|
|
"params": map[string]any{
|
|
|
|
|
"a": true,
|
|
|
|
|
},
|
|
|
|
|
}, &req)) {
|
|
|
|
|
assert.Equal(t, map[string]bool{
|
|
|
|
|
"a": true,
|
|
|
|
|
}, req.Params)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("bool map with error", func(t *testing.T) {
|
|
|
|
|
var req struct {
|
|
|
|
|
Params map[string]string `json:"params"`
|
|
|
|
|
}
|
|
|
|
|
assert.Equal(t, errTypeMismatch, UnmarshalJsonMap(map[string]any{
|
|
|
|
|
"params": map[string]any{
|
|
|
|
|
"a": true,
|
|
|
|
|
},
|
|
|
|
|
}, &req))
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestUnmarshalJsonBytesSliceOfMaps(t *testing.T) {
|
|
|
|
@ -4446,6 +4833,55 @@ func Test_UnmarshalMap(t *testing.T) {
|
|
|
|
|
var customer Customer
|
|
|
|
|
assert.ErrorIs(t, UnmarshalKey(input, &customer), errTypeMismatch)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("map from string", func(t *testing.T) {
|
|
|
|
|
type Customer struct {
|
|
|
|
|
Names map[string]string `key:"names,string"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
input := map[string]any{
|
|
|
|
|
"names": `{"name": "Tom"}`,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var customer Customer
|
|
|
|
|
assert.NoError(t, UnmarshalKey(input, &customer))
|
|
|
|
|
assert.Equal(t, "Tom", customer.Names["name"])
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("map from string with error", func(t *testing.T) {
|
|
|
|
|
type Customer struct {
|
|
|
|
|
Names map[string]any `key:"names,string"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
input := map[string]any{
|
|
|
|
|
"names": `"name"`,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var customer Customer
|
|
|
|
|
assert.Error(t, UnmarshalKey(input, &customer))
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// func TestUnmarshalWithFillPrimitives(t *testing.T) {
|
|
|
|
|
// t.Run("fill primitives", func(t *testing.T) {
|
|
|
|
|
// type St struct {
|
|
|
|
|
// A int `key:"a,string,range=[5,10]"`
|
|
|
|
|
// }
|
|
|
|
|
// var st St
|
|
|
|
|
// err := UnmarshalKey(map[string]any{
|
|
|
|
|
// "a": "1",
|
|
|
|
|
// }, &st)
|
|
|
|
|
// assert.ErrorIs(t, err, errNumberRange)
|
|
|
|
|
// })
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
func TestUnmarshaler_Unmarshal(t *testing.T) {
|
|
|
|
|
t.Run("not struct", func(t *testing.T) {
|
|
|
|
|
var i int
|
|
|
|
|
unmarshaler := NewUnmarshaler(jsonTagKey)
|
|
|
|
|
err := unmarshaler.UnmarshalValuer(nil, &i)
|
|
|
|
|
assert.Error(t, err)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestGetValueWithChainedKeys(t *testing.T) {
|
|
|
|
|