diff --git a/.example/other/test.go b/.example/other/test.go index d587b2a86..67760c9c5 100644 --- a/.example/other/test.go +++ b/.example/other/test.go @@ -1,10 +1,32 @@ package main import ( + "fmt" "github.com/gogf/gf/frame/g" - "os" + "github.com/gogf/gf/util/gconv" ) -func main() { - g.Dump(os.Args) +type TokenRequest struct { + Scope string + Watermark bool + Policy *g.Var +} + +func main() { + // s := ` + //{ + // "policy": {"name":"john"}, + // "scope": "pub-med-panel", + // "watermark": true + //} + //` + var t *TokenRequest + m := g.Map{ + "policy": g.Map{"name": "john"}, + "scope": "pub-med-panel", + "watermark": true, + } + err := gconv.Struct(m, &t) + fmt.Println(err) + fmt.Println(t.Policy) } diff --git a/container/garray/garray_normal_any.go b/container/garray/garray_normal_any.go index 7c977a47e..23e576f3b 100644 --- a/container/garray/garray_normal_any.go +++ b/container/garray/garray_normal_any.go @@ -719,3 +719,19 @@ func (a *Array) UnmarshalJSON(b []byte) error { } return nil } + +// UnmarshalValue is an interface implement which sets any type of value for array. +func (a *Array) UnmarshalValue(value interface{}) error { + if a.mu == nil { + a.mu = rwmutex.New() + } + a.mu.Lock() + defer a.mu.Unlock() + switch value.(type) { + case string, []byte: + return json.Unmarshal(gconv.Bytes(value), &a.array) + default: + a.array = gconv.SliceAny(value) + } + return nil +} diff --git a/container/garray/garray_normal_int.go b/container/garray/garray_normal_int.go index 31d5c4fed..86b589dc9 100644 --- a/container/garray/garray_normal_int.go +++ b/container/garray/garray_normal_int.go @@ -700,3 +700,19 @@ func (a *IntArray) UnmarshalJSON(b []byte) error { } return nil } + +// UnmarshalValue is an interface implement which sets any type of value for array. +func (a *IntArray) UnmarshalValue(value interface{}) error { + if a.mu == nil { + a.mu = rwmutex.New() + } + a.mu.Lock() + defer a.mu.Unlock() + switch value.(type) { + case string, []byte: + return json.Unmarshal(gconv.Bytes(value), &a.array) + default: + a.array = gconv.SliceInt(value) + } + return nil +} diff --git a/container/garray/garray_normal_str.go b/container/garray/garray_normal_str.go index b6b19603f..9317aad0c 100644 --- a/container/garray/garray_normal_str.go +++ b/container/garray/garray_normal_str.go @@ -700,3 +700,19 @@ func (a *StrArray) UnmarshalJSON(b []byte) error { } return nil } + +// UnmarshalValue is an interface implement which sets any type of value for array. +func (a *StrArray) UnmarshalValue(value interface{}) error { + if a.mu == nil { + a.mu = rwmutex.New() + } + a.mu.Lock() + defer a.mu.Unlock() + switch value.(type) { + case string, []byte: + return json.Unmarshal(gconv.Bytes(value), &a.array) + default: + a.array = gconv.SliceStr(value) + } + return nil +} diff --git a/container/garray/garray_sorted_any.go b/container/garray/garray_sorted_any.go index 2f4fb5605..d2f3947f5 100644 --- a/container/garray/garray_sorted_any.go +++ b/container/garray/garray_sorted_any.go @@ -655,10 +655,34 @@ func (a *SortedArray) UnmarshalJSON(b []byte) error { if err := json.Unmarshal(b, &a.array); err != nil { return err } - if a.comparator != nil { + if a.comparator != nil && a.array != nil { sort.Slice(a.array, func(i, j int) bool { return a.comparator(a.array[i], a.array[j]) < 0 }) } return nil } + +// UnmarshalValue is an interface implement which sets any type of value for array. +func (a *SortedArray) UnmarshalValue(value interface{}) (err error) { + if a.mu == nil { + a.mu = rwmutex.New() + a.unique = gtype.NewBool() + // Note that the comparator is string comparator in default. + a.comparator = gutil.ComparatorString + } + a.mu.Lock() + defer a.mu.Unlock() + switch value.(type) { + case string, []byte: + err = json.Unmarshal(gconv.Bytes(value), &a.array) + default: + a.array = gconv.SliceAny(value) + } + if a.comparator != nil && a.array != nil { + sort.Slice(a.array, func(i, j int) bool { + return a.comparator(a.array[i], a.array[j]) < 0 + }) + } + return err +} diff --git a/container/garray/garray_sorted_int.go b/container/garray/garray_sorted_int.go index 73888743e..b67f6f25c 100644 --- a/container/garray/garray_sorted_int.go +++ b/container/garray/garray_sorted_int.go @@ -629,6 +629,30 @@ func (a *SortedIntArray) UnmarshalJSON(b []byte) error { if err := json.Unmarshal(b, &a.array); err != nil { return err } - sort.Ints(a.array) + if a.array != nil { + sort.Ints(a.array) + } return nil } + +// UnmarshalValue is an interface implement which sets any type of value for array. +func (a *SortedIntArray) UnmarshalValue(value interface{}) (err error) { + if a.mu == nil { + a.mu = rwmutex.New() + a.unique = gtype.NewBool() + // Note that the comparator is string comparator in default. + a.comparator = defaultComparatorInt + } + a.mu.Lock() + defer a.mu.Unlock() + switch value.(type) { + case string, []byte: + err = json.Unmarshal(gconv.Bytes(value), &a.array) + default: + a.array = gconv.SliceInt(value) + } + if a.array != nil { + sort.Ints(a.array) + } + return err +} diff --git a/container/garray/garray_sorted_str.go b/container/garray/garray_sorted_str.go index be2c8b119..ca691d171 100644 --- a/container/garray/garray_sorted_str.go +++ b/container/garray/garray_sorted_str.go @@ -625,6 +625,30 @@ func (a *SortedStrArray) UnmarshalJSON(b []byte) error { if err := json.Unmarshal(b, &a.array); err != nil { return err } - sort.Strings(a.array) + if a.array != nil { + sort.Strings(a.array) + } return nil } + +// UnmarshalValue is an interface implement which sets any type of value for array. +func (a *SortedStrArray) UnmarshalValue(value interface{}) (err error) { + if a.mu == nil { + a.mu = rwmutex.New() + a.unique = gtype.NewBool() + // Note that the comparator is string comparator in default. + a.comparator = defaultComparatorStr + } + a.mu.Lock() + defer a.mu.Unlock() + switch value.(type) { + case string, []byte: + err = json.Unmarshal(gconv.Bytes(value), &a.array) + default: + a.array = gconv.SliceStr(value) + } + if a.array != nil { + sort.Strings(a.array) + } + return err +} diff --git a/container/garray/garray_z_unit_normal_any_array_test.go b/container/garray/garray_z_unit_normal_any_array_test.go index a03060336..5d08275c6 100644 --- a/container/garray/garray_z_unit_normal_any_array_test.go +++ b/container/garray/garray_z_unit_normal_any_array_test.go @@ -511,3 +511,32 @@ func TestArray_RemoveValue(t *testing.T) { gtest.Assert(array.RemoveValue("f"), false) }) } + +func TestArray_UnmarshalValue(t *testing.T) { + type T struct { + Name string + Array *garray.Array + } + // JSON + gtest.Case(t, func() { + var t *T + err := gconv.Struct(g.Map{ + "name": "john", + "array": []byte(`[1,2,3]`), + }, &t) + gtest.Assert(err, nil) + gtest.Assert(t.Name, "john") + gtest.Assert(t.Array.Slice(), g.Slice{1, 2, 3}) + }) + // Map + gtest.Case(t, func() { + var t *T + err := gconv.Struct(g.Map{ + "name": "john", + "array": g.Slice{1, 2, 3}, + }, &t) + gtest.Assert(err, nil) + gtest.Assert(t.Name, "john") + gtest.Assert(t.Array.Slice(), g.Slice{1, 2, 3}) + }) +} diff --git a/container/garray/garray_z_unit_normal_int_array_test.go b/container/garray/garray_z_unit_normal_int_array_test.go index aa2d55678..748d346eb 100644 --- a/container/garray/garray_z_unit_normal_int_array_test.go +++ b/container/garray/garray_z_unit_normal_int_array_test.go @@ -546,3 +546,32 @@ func TestIntArray_RemoveValue(t *testing.T) { gtest.Assert(array.Len(), 2) }) } + +func TestIntArray_UnmarshalValue(t *testing.T) { + type T struct { + Name string + Array *garray.IntArray + } + // JSON + gtest.Case(t, func() { + var t *T + err := gconv.Struct(g.Map{ + "name": "john", + "array": []byte(`[1,2,3]`), + }, &t) + gtest.Assert(err, nil) + gtest.Assert(t.Name, "john") + gtest.Assert(t.Array.Slice(), g.Slice{1, 2, 3}) + }) + // Map + gtest.Case(t, func() { + var t *T + err := gconv.Struct(g.Map{ + "name": "john", + "array": g.Slice{1, 2, 3}, + }, &t) + gtest.Assert(err, nil) + gtest.Assert(t.Name, "john") + gtest.Assert(t.Array.Slice(), g.Slice{1, 2, 3}) + }) +} diff --git a/container/garray/garray_z_unit_normal_str_array_test.go b/container/garray/garray_z_unit_normal_str_array_test.go index 2950b23e2..0d1bedaf6 100644 --- a/container/garray/garray_z_unit_normal_str_array_test.go +++ b/container/garray/garray_z_unit_normal_str_array_test.go @@ -549,3 +549,32 @@ func TestStrArray_RemoveValue(t *testing.T) { gtest.Assert(array.RemoveValue("f"), false) }) } + +func TestStrArray_UnmarshalValue(t *testing.T) { + type T struct { + Name string + Array *garray.StrArray + } + // JSON + gtest.Case(t, func() { + var t *T + err := gconv.Struct(g.Map{ + "name": "john", + "array": []byte(`["1","2","3"]`), + }, &t) + gtest.Assert(err, nil) + gtest.Assert(t.Name, "john") + gtest.Assert(t.Array.Slice(), g.SliceStr{"1", "2", "3"}) + }) + // Map + gtest.Case(t, func() { + var t *T + err := gconv.Struct(g.Map{ + "name": "john", + "array": g.SliceStr{"1", "2", "3"}, + }, &t) + gtest.Assert(err, nil) + gtest.Assert(t.Name, "john") + gtest.Assert(t.Array.Slice(), g.SliceStr{"1", "2", "3"}) + }) +} diff --git a/container/garray/garray_z_unit_sorted_any_array_test.go b/container/garray/garray_z_unit_sorted_any_array_test.go index eb91fe5f7..f824f8d32 100644 --- a/container/garray/garray_z_unit_sorted_any_array_test.go +++ b/container/garray/garray_z_unit_sorted_any_array_test.go @@ -649,3 +649,32 @@ func TestSortedArray_RemoveValue(t *testing.T) { gtest.Assert(array.RemoveValue("f"), false) }) } + +func TestSortedArray_UnmarshalValue(t *testing.T) { + type T struct { + Name string + Array *garray.SortedArray + } + // JSON + gtest.Case(t, func() { + var t *T + err := gconv.Struct(g.Map{ + "name": "john", + "array": []byte(`[2,3,1]`), + }, &t) + gtest.Assert(err, nil) + gtest.Assert(t.Name, "john") + gtest.Assert(t.Array.Slice(), g.Slice{1, 2, 3}) + }) + // Map + gtest.Case(t, func() { + var t *T + err := gconv.Struct(g.Map{ + "name": "john", + "array": g.Slice{2, 3, 1}, + }, &t) + gtest.Assert(err, nil) + gtest.Assert(t.Name, "john") + gtest.Assert(t.Array.Slice(), g.Slice{1, 2, 3}) + }) +} diff --git a/container/garray/garray_z_unit_sorted_int_array_test.go b/container/garray/garray_z_unit_sorted_int_array_test.go index d219ef79a..47459759c 100644 --- a/container/garray/garray_z_unit_sorted_int_array_test.go +++ b/container/garray/garray_z_unit_sorted_int_array_test.go @@ -530,3 +530,32 @@ func TestSortedIntArray_RemoveValue(t *testing.T) { gtest.Assert(array.Len(), 2) }) } + +func TestSortedIntArray_UnmarshalValue(t *testing.T) { + type T struct { + Name string + Array *garray.SortedIntArray + } + // JSON + gtest.Case(t, func() { + var t *T + err := gconv.Struct(g.Map{ + "name": "john", + "array": []byte(`[2,3,1]`), + }, &t) + gtest.Assert(err, nil) + gtest.Assert(t.Name, "john") + gtest.Assert(t.Array.Slice(), g.Slice{1, 2, 3}) + }) + // Map + gtest.Case(t, func() { + var t *T + err := gconv.Struct(g.Map{ + "name": "john", + "array": g.Slice{2, 3, 1}, + }, &t) + gtest.Assert(err, nil) + gtest.Assert(t.Name, "john") + gtest.Assert(t.Array.Slice(), g.Slice{1, 2, 3}) + }) +} diff --git a/container/garray/garray_z_unit_sorted_str_array_test.go b/container/garray/garray_z_unit_sorted_str_array_test.go index 23980bf57..2a9a6bbcf 100644 --- a/container/garray/garray_z_unit_sorted_str_array_test.go +++ b/container/garray/garray_z_unit_sorted_str_array_test.go @@ -539,3 +539,32 @@ func TestSortedStrArray_RemoveValue(t *testing.T) { gtest.Assert(array.RemoveValue("f"), false) }) } + +func TestSortedStrArray_UnmarshalValue(t *testing.T) { + type T struct { + Name string + Array *garray.SortedStrArray + } + // JSON + gtest.Case(t, func() { + var t *T + err := gconv.Struct(g.Map{ + "name": "john", + "array": []byte(`["1","3","2"]`), + }, &t) + gtest.Assert(err, nil) + gtest.Assert(t.Name, "john") + gtest.Assert(t.Array.Slice(), g.SliceStr{"1", "2", "3"}) + }) + // Map + gtest.Case(t, func() { + var t *T + err := gconv.Struct(g.Map{ + "name": "john", + "array": g.SliceStr{"1", "3", "2"}, + }, &t) + gtest.Assert(err, nil) + gtest.Assert(t.Name, "john") + gtest.Assert(t.Array.Slice(), g.SliceStr{"1", "2", "3"}) + }) +} diff --git a/container/glist/glist.go b/container/glist/glist.go index 26eb49056..9e8dce8c1 100644 --- a/container/glist/glist.go +++ b/container/glist/glist.go @@ -438,3 +438,22 @@ func (l *List) UnmarshalJSON(b []byte) error { l.PushBacks(array) return nil } + +// UnmarshalValue is an interface implement which sets any type of value for list. +func (l *List) UnmarshalValue(value interface{}) (err error) { + if l.mu == nil { + l.mu = rwmutex.New() + l.list = list.New() + } + l.mu.Lock() + defer l.mu.Unlock() + var array []interface{} + switch value.(type) { + case string, []byte: + err = json.Unmarshal(gconv.Bytes(value), &array) + default: + array = gconv.SliceAny(value) + } + l.PushBacks(array) + return err +} diff --git a/container/glist/glist_z_unit_test.go b/container/glist/glist_z_unit_test.go index c1fe8b56d..81fdeef08 100644 --- a/container/glist/glist_z_unit_test.go +++ b/container/glist/glist_z_unit_test.go @@ -632,3 +632,32 @@ func TestList_Json(t *testing.T) { gtest.Assert(l.FrontAll(), a) }) } + +func TestList_UnmarshalValue(t *testing.T) { + type T struct { + Name string + List *List + } + // JSON + gtest.Case(t, func() { + var t *T + err := gconv.Struct(map[string]interface{}{ + "name": "john", + "list": []byte(`[1,2,3]`), + }, &t) + gtest.Assert(err, nil) + gtest.Assert(t.Name, "john") + gtest.Assert(t.List.FrontAll(), []interface{}{1, 2, 3}) + }) + // Map + gtest.Case(t, func() { + var t *T + err := gconv.Struct(map[string]interface{}{ + "name": "john", + "list": []interface{}{1, 2, 3}, + }, &t) + gtest.Assert(err, nil) + gtest.Assert(t.Name, "john") + gtest.Assert(t.List.FrontAll(), []interface{}{1, 2, 3}) + }) +} diff --git a/container/gmap/gmap_hash_any_any_map.go b/container/gmap/gmap_hash_any_any_map.go index 5b8709a7c..2a2b3c279 100644 --- a/container/gmap/gmap_hash_any_any_map.go +++ b/container/gmap/gmap_hash_any_any_map.go @@ -436,3 +436,17 @@ func (m *AnyAnyMap) UnmarshalJSON(b []byte) error { } return nil } + +// UnmarshalValue is an interface implement which sets any type of value for map. +func (m *AnyAnyMap) UnmarshalValue(value interface{}) (err error) { + if m.mu == nil { + m.mu = rwmutex.New() + m.data = make(map[interface{}]interface{}) + } + m.mu.Lock() + defer m.mu.Unlock() + for k, v := range gconv.Map(value) { + m.data[k] = v + } + return +} diff --git a/container/gmap/gmap_hash_int_any_map.go b/container/gmap/gmap_hash_int_any_map.go index 677bd77a8..8c3479add 100644 --- a/container/gmap/gmap_hash_int_any_map.go +++ b/container/gmap/gmap_hash_int_any_map.go @@ -432,3 +432,22 @@ func (m *IntAnyMap) UnmarshalJSON(b []byte) error { } return nil } + +// UnmarshalValue is an interface implement which sets any type of value for map. +func (m *IntAnyMap) UnmarshalValue(value interface{}) (err error) { + if m.mu == nil { + m.mu = rwmutex.New() + m.data = make(map[int]interface{}) + } + m.mu.Lock() + defer m.mu.Unlock() + switch value.(type) { + case string, []byte: + return json.Unmarshal(gconv.Bytes(value), &m.data) + default: + for k, v := range gconv.Map(value) { + m.data[gconv.Int(k)] = v + } + } + return +} diff --git a/container/gmap/gmap_hash_int_int_map.go b/container/gmap/gmap_hash_int_int_map.go index f93f0f7a4..826ac3d59 100644 --- a/container/gmap/gmap_hash_int_int_map.go +++ b/container/gmap/gmap_hash_int_int_map.go @@ -409,3 +409,22 @@ func (m *IntIntMap) UnmarshalJSON(b []byte) error { } return nil } + +// UnmarshalValue is an interface implement which sets any type of value for map. +func (m *IntIntMap) UnmarshalValue(value interface{}) (err error) { + if m.mu == nil { + m.mu = rwmutex.New() + m.data = make(map[int]int) + } + m.mu.Lock() + defer m.mu.Unlock() + switch value.(type) { + case string, []byte: + return json.Unmarshal(gconv.Bytes(value), &m.data) + default: + for k, v := range gconv.Map(value) { + m.data[gconv.Int(k)] = gconv.Int(v) + } + } + return +} diff --git a/container/gmap/gmap_hash_int_str_map.go b/container/gmap/gmap_hash_int_str_map.go index fb7340633..5db6b23f8 100644 --- a/container/gmap/gmap_hash_int_str_map.go +++ b/container/gmap/gmap_hash_int_str_map.go @@ -410,3 +410,22 @@ func (m *IntStrMap) UnmarshalJSON(b []byte) error { } return nil } + +// UnmarshalValue is an interface implement which sets any type of value for map. +func (m *IntStrMap) UnmarshalValue(value interface{}) (err error) { + if m.mu == nil { + m.mu = rwmutex.New() + m.data = make(map[int]string) + } + m.mu.Lock() + defer m.mu.Unlock() + switch value.(type) { + case string, []byte: + return json.Unmarshal(gconv.Bytes(value), &m.data) + default: + for k, v := range gconv.Map(value) { + m.data[gconv.Int(k)] = gconv.String(v) + } + } + return +} diff --git a/container/gmap/gmap_hash_str_any_map.go b/container/gmap/gmap_hash_str_any_map.go index feaf3da4a..cd7925c08 100644 --- a/container/gmap/gmap_hash_str_any_map.go +++ b/container/gmap/gmap_hash_str_any_map.go @@ -428,3 +428,15 @@ func (m *StrAnyMap) UnmarshalJSON(b []byte) error { } return nil } + +// UnmarshalValue is an interface implement which sets any type of value for map. +func (m *StrAnyMap) UnmarshalValue(value interface{}) (err error) { + if m.mu == nil { + m.mu = rwmutex.New() + m.data = make(map[string]interface{}) + } + m.mu.Lock() + defer m.mu.Unlock() + m.data = gconv.Map(value) + return +} diff --git a/container/gmap/gmap_hash_str_int_map.go b/container/gmap/gmap_hash_str_int_map.go index 04ed0669e..2f98237c3 100644 --- a/container/gmap/gmap_hash_str_int_map.go +++ b/container/gmap/gmap_hash_str_int_map.go @@ -411,3 +411,22 @@ func (m *StrIntMap) UnmarshalJSON(b []byte) error { } return nil } + +// UnmarshalValue is an interface implement which sets any type of value for map. +func (m *StrIntMap) UnmarshalValue(value interface{}) (err error) { + if m.mu == nil { + m.mu = rwmutex.New() + m.data = make(map[string]int) + } + m.mu.Lock() + defer m.mu.Unlock() + switch value.(type) { + case string, []byte: + return json.Unmarshal(gconv.Bytes(value), &m.data) + default: + for k, v := range gconv.Map(value) { + m.data[k] = gconv.Int(v) + } + } + return +} diff --git a/container/gmap/gmap_hash_str_str_map.go b/container/gmap/gmap_hash_str_str_map.go index b38043ab5..669b48033 100644 --- a/container/gmap/gmap_hash_str_str_map.go +++ b/container/gmap/gmap_hash_str_str_map.go @@ -9,6 +9,7 @@ package gmap import ( "encoding/json" + "github.com/gogf/gf/util/gconv" "github.com/gogf/gf/internal/empty" @@ -412,3 +413,14 @@ func (m *StrStrMap) UnmarshalJSON(b []byte) error { } return nil } + +// UnmarshalValue is an interface implement which sets any type of value for map. +func (m *StrStrMap) UnmarshalValue(value interface{}) (err error) { + if m.mu == nil { + m.mu = rwmutex.New() + } + m.mu.Lock() + defer m.mu.Unlock() + m.data = gconv.MapStrStr(value) + return +} diff --git a/container/gmap/gmap_list_map.go b/container/gmap/gmap_list_map.go index eaee3ab1b..349a50f56 100644 --- a/container/gmap/gmap_list_map.go +++ b/container/gmap/gmap_list_map.go @@ -491,3 +491,22 @@ func (m *ListMap) UnmarshalJSON(b []byte) error { } return nil } + +// UnmarshalValue is an interface implement which sets any type of value for map. +func (m *ListMap) UnmarshalValue(value interface{}) (err error) { + if m.mu == nil { + m.mu = rwmutex.New() + m.data = make(map[interface{}]*glist.Element) + m.list = glist.New() + } + m.mu.Lock() + defer m.mu.Unlock() + for k, v := range gconv.Map(value) { + if e, ok := m.data[k]; !ok { + m.data[k] = m.list.PushBack(&gListMapNode{k, v}) + } else { + e.Value = &gListMapNode{k, v} + } + } + return +} diff --git a/container/gmap/gmap_z_unit_any_any_test.go b/container/gmap/gmap_z_unit_any_any_test.go index 39af9a5fb..31f6162d7 100644 --- a/container/gmap/gmap_z_unit_any_any_test.go +++ b/container/gmap/gmap_z_unit_any_any_test.go @@ -275,3 +275,39 @@ func Test_AnyAnyMap_Pops(t *testing.T) { gtest.Assert(vArray.Unique().Len(), 3) }) } + +func TestAnyAnyMap_UnmarshalValue(t *testing.T) { + type T struct { + Name string + Map *gmap.Map + } + // JSON + gtest.Case(t, func() { + var t *T + err := gconv.Struct(map[string]interface{}{ + "name": "john", + "map": []byte(`{"k1":"v1","k2":"v2"}`), + }, &t) + gtest.Assert(err, nil) + gtest.Assert(t.Name, "john") + gtest.Assert(t.Map.Size(), 2) + gtest.Assert(t.Map.Get("k1"), "v1") + gtest.Assert(t.Map.Get("k2"), "v2") + }) + // Map + gtest.Case(t, func() { + var t *T + err := gconv.Struct(map[string]interface{}{ + "name": "john", + "map": g.Map{ + "k1": "v1", + "k2": "v2", + }, + }, &t) + gtest.Assert(err, nil) + gtest.Assert(t.Name, "john") + gtest.Assert(t.Map.Size(), 2) + gtest.Assert(t.Map.Get("k1"), "v1") + gtest.Assert(t.Map.Get("k2"), "v2") + }) +} diff --git a/container/gmap/gmap_z_unit_int_any_test.go b/container/gmap/gmap_z_unit_int_any_test.go index 4f06189f9..4d0438422 100644 --- a/container/gmap/gmap_z_unit_int_any_test.go +++ b/container/gmap/gmap_z_unit_int_any_test.go @@ -10,6 +10,7 @@ import ( "encoding/json" "github.com/gogf/gf/container/garray" "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/util/gconv" "testing" "github.com/gogf/gf/container/gmap" @@ -257,3 +258,39 @@ func Test_IntAnyMap_Pops(t *testing.T) { gtest.Assert(vArray.Unique().Len(), 3) }) } + +func TestIntAnyMap_UnmarshalValue(t *testing.T) { + type T struct { + Name string + Map *gmap.IntAnyMap + } + // JSON + gtest.Case(t, func() { + var t *T + err := gconv.Struct(map[string]interface{}{ + "name": "john", + "map": []byte(`{"1":"v1","2":"v2"}`), + }, &t) + gtest.Assert(err, nil) + gtest.Assert(t.Name, "john") + gtest.Assert(t.Map.Size(), 2) + gtest.Assert(t.Map.Get(1), "v1") + gtest.Assert(t.Map.Get(2), "v2") + }) + // Map + gtest.Case(t, func() { + var t *T + err := gconv.Struct(map[string]interface{}{ + "name": "john", + "map": g.MapIntAny{ + 1: "v1", + 2: "v2", + }, + }, &t) + gtest.Assert(err, nil) + gtest.Assert(t.Name, "john") + gtest.Assert(t.Map.Size(), 2) + gtest.Assert(t.Map.Get(1), "v1") + gtest.Assert(t.Map.Get(2), "v2") + }) +} diff --git a/container/gmap/gmap_z_unit_int_int_test.go b/container/gmap/gmap_z_unit_int_int_test.go index 070a3b628..b6214d58f 100644 --- a/container/gmap/gmap_z_unit_int_int_test.go +++ b/container/gmap/gmap_z_unit_int_int_test.go @@ -10,6 +10,7 @@ import ( "encoding/json" "github.com/gogf/gf/container/garray" "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/util/gconv" "testing" "github.com/gogf/gf/container/gmap" @@ -260,3 +261,39 @@ func Test_IntIntMap_Pops(t *testing.T) { gtest.Assert(vArray.Unique().Len(), 3) }) } + +func TestIntIntMap_UnmarshalValue(t *testing.T) { + type T struct { + Name string + Map *gmap.IntIntMap + } + // JSON + gtest.Case(t, func() { + var t *T + err := gconv.Struct(map[string]interface{}{ + "name": "john", + "map": []byte(`{"1":1,"2":2}`), + }, &t) + gtest.Assert(err, nil) + gtest.Assert(t.Name, "john") + gtest.Assert(t.Map.Size(), 2) + gtest.Assert(t.Map.Get(1), "1") + gtest.Assert(t.Map.Get(2), "2") + }) + // Map + gtest.Case(t, func() { + var t *T + err := gconv.Struct(map[string]interface{}{ + "name": "john", + "map": g.MapIntAny{ + 1: 1, + 2: 2, + }, + }, &t) + gtest.Assert(err, nil) + gtest.Assert(t.Name, "john") + gtest.Assert(t.Map.Size(), 2) + gtest.Assert(t.Map.Get(1), "1") + gtest.Assert(t.Map.Get(2), "2") + }) +} diff --git a/container/gmap/gmap_z_unit_int_str_test.go b/container/gmap/gmap_z_unit_int_str_test.go index 541946b1a..f36c576f0 100644 --- a/container/gmap/gmap_z_unit_int_str_test.go +++ b/container/gmap/gmap_z_unit_int_str_test.go @@ -10,6 +10,7 @@ import ( "encoding/json" "github.com/gogf/gf/container/garray" "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/util/gconv" "testing" "github.com/gogf/gf/container/gmap" @@ -261,3 +262,39 @@ func Test_IntStrMap_Pops(t *testing.T) { gtest.Assert(vArray.Unique().Len(), 3) }) } + +func TestIntStrMap_UnmarshalValue(t *testing.T) { + type T struct { + Name string + Map *gmap.IntStrMap + } + // JSON + gtest.Case(t, func() { + var t *T + err := gconv.Struct(map[string]interface{}{ + "name": "john", + "map": []byte(`{"1":"v1","2":"v2"}`), + }, &t) + gtest.Assert(err, nil) + gtest.Assert(t.Name, "john") + gtest.Assert(t.Map.Size(), 2) + gtest.Assert(t.Map.Get(1), "v1") + gtest.Assert(t.Map.Get(2), "v2") + }) + // Map + gtest.Case(t, func() { + var t *T + err := gconv.Struct(map[string]interface{}{ + "name": "john", + "map": g.MapIntAny{ + 1: "v1", + 2: "v2", + }, + }, &t) + gtest.Assert(err, nil) + gtest.Assert(t.Name, "john") + gtest.Assert(t.Map.Size(), 2) + gtest.Assert(t.Map.Get(1), "v1") + gtest.Assert(t.Map.Get(2), "v2") + }) +} diff --git a/container/gmap/gmap_z_unit_list_map_test.go b/container/gmap/gmap_z_unit_list_map_test.go index 4b1c53b36..7829bf16d 100644 --- a/container/gmap/gmap_z_unit_list_map_test.go +++ b/container/gmap/gmap_z_unit_list_map_test.go @@ -231,3 +231,39 @@ func Test_ListMap_Pops(t *testing.T) { gtest.Assert(vArray.Unique().Len(), 3) }) } + +func TestListMap_UnmarshalValue(t *testing.T) { + type T struct { + Name string + Map *gmap.ListMap + } + // JSON + gtest.Case(t, func() { + var t *T + err := gconv.Struct(map[string]interface{}{ + "name": "john", + "map": []byte(`{"1":"v1","2":"v2"}`), + }, &t) + gtest.Assert(err, nil) + gtest.Assert(t.Name, "john") + gtest.Assert(t.Map.Size(), 2) + gtest.Assert(t.Map.Get("1"), "v1") + gtest.Assert(t.Map.Get("2"), "v2") + }) + // Map + gtest.Case(t, func() { + var t *T + err := gconv.Struct(map[string]interface{}{ + "name": "john", + "map": g.MapIntAny{ + 1: "v1", + 2: "v2", + }, + }, &t) + gtest.Assert(err, nil) + gtest.Assert(t.Name, "john") + gtest.Assert(t.Map.Size(), 2) + gtest.Assert(t.Map.Get("1"), "v1") + gtest.Assert(t.Map.Get("2"), "v2") + }) +} diff --git a/container/gmap/gmap_z_unit_str_any_test.go b/container/gmap/gmap_z_unit_str_any_test.go index e5a05ec95..d47f31413 100644 --- a/container/gmap/gmap_z_unit_str_any_test.go +++ b/container/gmap/gmap_z_unit_str_any_test.go @@ -10,6 +10,7 @@ import ( "encoding/json" "github.com/gogf/gf/container/garray" "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/util/gconv" "testing" "github.com/gogf/gf/container/gmap" @@ -269,3 +270,39 @@ func Test_StrAnyMap_Pops(t *testing.T) { gtest.Assert(vArray.Unique().Len(), 3) }) } + +func TestStrAnyMap_UnmarshalValue(t *testing.T) { + type T struct { + Name string + Map *gmap.StrAnyMap + } + // JSON + gtest.Case(t, func() { + var t *T + err := gconv.Struct(map[string]interface{}{ + "name": "john", + "map": []byte(`{"k1":"v1","k2":"v2"}`), + }, &t) + gtest.Assert(err, nil) + gtest.Assert(t.Name, "john") + gtest.Assert(t.Map.Size(), 2) + gtest.Assert(t.Map.Get("k1"), "v1") + gtest.Assert(t.Map.Get("k2"), "v2") + }) + // Map + gtest.Case(t, func() { + var t *T + err := gconv.Struct(map[string]interface{}{ + "name": "john", + "map": g.Map{ + "k1": "v1", + "k2": "v2", + }, + }, &t) + gtest.Assert(err, nil) + gtest.Assert(t.Name, "john") + gtest.Assert(t.Map.Size(), 2) + gtest.Assert(t.Map.Get("k1"), "v1") + gtest.Assert(t.Map.Get("k2"), "v2") + }) +} diff --git a/container/gmap/gmap_z_unit_str_int_test.go b/container/gmap/gmap_z_unit_str_int_test.go index ba20d8103..c7f6ab407 100644 --- a/container/gmap/gmap_z_unit_str_int_test.go +++ b/container/gmap/gmap_z_unit_str_int_test.go @@ -10,6 +10,7 @@ import ( "encoding/json" "github.com/gogf/gf/container/garray" "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/util/gconv" "testing" "github.com/gogf/gf/container/gmap" @@ -272,3 +273,39 @@ func Test_StrIntMap_Pops(t *testing.T) { gtest.Assert(vArray.Unique().Len(), 3) }) } + +func TestStrIntMap_UnmarshalValue(t *testing.T) { + type T struct { + Name string + Map *gmap.StrIntMap + } + // JSON + gtest.Case(t, func() { + var t *T + err := gconv.Struct(map[string]interface{}{ + "name": "john", + "map": []byte(`{"k1":1,"k2":2}`), + }, &t) + gtest.Assert(err, nil) + gtest.Assert(t.Name, "john") + gtest.Assert(t.Map.Size(), 2) + gtest.Assert(t.Map.Get("k1"), 1) + gtest.Assert(t.Map.Get("k2"), 2) + }) + // Map + gtest.Case(t, func() { + var t *T + err := gconv.Struct(map[string]interface{}{ + "name": "john", + "map": g.Map{ + "k1": 1, + "k2": 2, + }, + }, &t) + gtest.Assert(err, nil) + gtest.Assert(t.Name, "john") + gtest.Assert(t.Map.Size(), 2) + gtest.Assert(t.Map.Get("k1"), 1) + gtest.Assert(t.Map.Get("k2"), 2) + }) +} diff --git a/container/gmap/gmap_z_unit_str_str_test.go b/container/gmap/gmap_z_unit_str_str_test.go index 1105d5475..6906818a3 100644 --- a/container/gmap/gmap_z_unit_str_str_test.go +++ b/container/gmap/gmap_z_unit_str_str_test.go @@ -10,6 +10,7 @@ import ( "encoding/json" "github.com/gogf/gf/container/garray" "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/util/gconv" "testing" "github.com/gogf/gf/container/gmap" @@ -269,3 +270,39 @@ func Test_StrStrMap_Pops(t *testing.T) { gtest.Assert(vArray.Unique().Len(), 3) }) } + +func TestStrStrMap_UnmarshalValue(t *testing.T) { + type T struct { + Name string + Map *gmap.StrStrMap + } + // JSON + gtest.Case(t, func() { + var t *T + err := gconv.Struct(map[string]interface{}{ + "name": "john", + "map": []byte(`{"k1":"v1","k2":"v2"}`), + }, &t) + gtest.Assert(err, nil) + gtest.Assert(t.Name, "john") + gtest.Assert(t.Map.Size(), 2) + gtest.Assert(t.Map.Get("k1"), "v1") + gtest.Assert(t.Map.Get("k2"), "v2") + }) + // Map + gtest.Case(t, func() { + var t *T + err := gconv.Struct(map[string]interface{}{ + "name": "john", + "map": g.Map{ + "k1": "v1", + "k2": "v2", + }, + }, &t) + gtest.Assert(err, nil) + gtest.Assert(t.Name, "john") + gtest.Assert(t.Map.Size(), 2) + gtest.Assert(t.Map.Get("k1"), "v1") + gtest.Assert(t.Map.Get("k2"), "v2") + }) +} diff --git a/container/gmap/gmap_z_unit_tree_map_test.go b/container/gmap/gmap_z_unit_tree_map_test.go index 9b70e1c2c..1578142ec 100644 --- a/container/gmap/gmap_z_unit_tree_map_test.go +++ b/container/gmap/gmap_z_unit_tree_map_test.go @@ -148,3 +148,39 @@ func Test_TreeMap_Json(t *testing.T) { gtest.Assert(m.Get("k2"), data["k2"]) }) } + +func TestTreeMap_UnmarshalValue(t *testing.T) { + type T struct { + Name string + Map *gmap.TreeMap + } + // JSON + gtest.Case(t, func() { + var t *T + err := gconv.Struct(map[string]interface{}{ + "name": "john", + "map": []byte(`{"k1":"v1","k2":"v2"}`), + }, &t) + gtest.Assert(err, nil) + gtest.Assert(t.Name, "john") + gtest.Assert(t.Map.Size(), 2) + gtest.Assert(t.Map.Get("k1"), "v1") + gtest.Assert(t.Map.Get("k2"), "v2") + }) + // Map + gtest.Case(t, func() { + var t *T + err := gconv.Struct(map[string]interface{}{ + "name": "john", + "map": g.Map{ + "k1": "v1", + "k2": "v2", + }, + }, &t) + gtest.Assert(err, nil) + gtest.Assert(t.Name, "john") + gtest.Assert(t.Map.Size(), 2) + gtest.Assert(t.Map.Get("k1"), "v1") + gtest.Assert(t.Map.Get("k2"), "v2") + }) +} diff --git a/container/gset/gset_any_set.go b/container/gset/gset_any_set.go index bb7474413..175329546 100644 --- a/container/gset/gset_any_set.go +++ b/container/gset/gset_any_set.go @@ -430,3 +430,24 @@ func (set *Set) UnmarshalJSON(b []byte) error { } return nil } + +// UnmarshalValue is an interface implement which sets any type of value for set. +func (set *Set) UnmarshalValue(value interface{}) (err error) { + if set.mu == nil { + set.mu = rwmutex.New() + set.data = make(map[interface{}]struct{}) + } + set.mu.Lock() + defer set.mu.Unlock() + var array []interface{} + switch value.(type) { + case string, []byte: + err = json.Unmarshal(gconv.Bytes(value), &array) + default: + array = gconv.SliceAny(value) + } + for _, v := range array { + set.data[v] = struct{}{} + } + return +} diff --git a/container/gset/gset_int_set.go b/container/gset/gset_int_set.go index 0ed01a143..f853700a3 100644 --- a/container/gset/gset_int_set.go +++ b/container/gset/gset_int_set.go @@ -401,3 +401,24 @@ func (set *IntSet) UnmarshalJSON(b []byte) error { } return nil } + +// UnmarshalValue is an interface implement which sets any type of value for set. +func (set *IntSet) UnmarshalValue(value interface{}) (err error) { + if set.mu == nil { + set.mu = rwmutex.New() + set.data = make(map[int]struct{}) + } + set.mu.Lock() + defer set.mu.Unlock() + var array []int + switch value.(type) { + case string, []byte: + err = json.Unmarshal(gconv.Bytes(value), &array) + default: + array = gconv.SliceInt(value) + } + for _, v := range array { + set.data[v] = struct{}{} + } + return +} diff --git a/container/gset/gset_str_set.go b/container/gset/gset_str_set.go index 063c8ff91..cd4ce4723 100644 --- a/container/gset/gset_str_set.go +++ b/container/gset/gset_str_set.go @@ -417,3 +417,24 @@ func (set *StrSet) UnmarshalJSON(b []byte) error { } return nil } + +// UnmarshalValue is an interface implement which sets any type of value for set. +func (set *StrSet) UnmarshalValue(value interface{}) (err error) { + if set.mu == nil { + set.mu = rwmutex.New() + set.data = make(map[string]struct{}) + } + set.mu.Lock() + defer set.mu.Unlock() + var array []string + switch value.(type) { + case string, []byte: + err = json.Unmarshal(gconv.Bytes(value), &array) + default: + array = gconv.SliceStr(value) + } + for _, v := range array { + set.data[v] = struct{}{} + } + return +} diff --git a/container/gset/gset_z_unit_any_test.go b/container/gset/gset_z_unit_any_test.go index c53741dff..ac9a80e66 100644 --- a/container/gset/gset_z_unit_any_test.go +++ b/container/gset/gset_z_unit_any_test.go @@ -10,6 +10,8 @@ package gset_test import ( "encoding/json" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/util/gconv" "strings" "github.com/gogf/gf/container/garray" @@ -361,3 +363,40 @@ func TestSet_AddIfNotExistFunc(t *testing.T) { gtest.Assert(s.Contains(4), false) }) } + +func TestSet_UnmarshalValue(t *testing.T) { + type T struct { + Name string + Set *gset.Set + } + // JSON + gtest.Case(t, func() { + var t *T + err := gconv.Struct(g.Map{ + "name": "john", + "set": []byte(`["k1","k2","k3"]`), + }, &t) + gtest.Assert(err, nil) + gtest.Assert(t.Name, "john") + gtest.Assert(t.Set.Size(), 3) + gtest.Assert(t.Set.Contains("k1"), true) + gtest.Assert(t.Set.Contains("k2"), true) + gtest.Assert(t.Set.Contains("k3"), true) + gtest.Assert(t.Set.Contains("k4"), false) + }) + // Map + gtest.Case(t, func() { + var t *T + err := gconv.Struct(g.Map{ + "name": "john", + "set": g.Slice{"k1", "k2", "k3"}, + }, &t) + gtest.Assert(err, nil) + gtest.Assert(t.Name, "john") + gtest.Assert(t.Set.Size(), 3) + gtest.Assert(t.Set.Contains("k1"), true) + gtest.Assert(t.Set.Contains("k2"), true) + gtest.Assert(t.Set.Contains("k3"), true) + gtest.Assert(t.Set.Contains("k4"), false) + }) +} diff --git a/container/gset/gset_z_unit_int_test.go b/container/gset/gset_z_unit_int_test.go index 70886c277..f24491454 100644 --- a/container/gset/gset_z_unit_int_test.go +++ b/container/gset/gset_z_unit_int_test.go @@ -10,6 +10,8 @@ package gset_test import ( "encoding/json" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/util/gconv" "strings" "testing" @@ -324,3 +326,40 @@ func TestIntSet_AddIfNotExistFunc(t *testing.T) { gtest.Assert(s.Contains(4), false) }) } + +func TestIntSet_UnmarshalValue(t *testing.T) { + type T struct { + Name string + Set *gset.IntSet + } + // JSON + gtest.Case(t, func() { + var t *T + err := gconv.Struct(g.Map{ + "name": "john", + "set": []byte(`[1,2,3]`), + }, &t) + gtest.Assert(err, nil) + gtest.Assert(t.Name, "john") + gtest.Assert(t.Set.Size(), 3) + gtest.Assert(t.Set.Contains(1), true) + gtest.Assert(t.Set.Contains(2), true) + gtest.Assert(t.Set.Contains(3), true) + gtest.Assert(t.Set.Contains(4), false) + }) + // Map + gtest.Case(t, func() { + var t *T + err := gconv.Struct(g.Map{ + "name": "john", + "set": g.Slice{1, 2, 3}, + }, &t) + gtest.Assert(err, nil) + gtest.Assert(t.Name, "john") + gtest.Assert(t.Set.Size(), 3) + gtest.Assert(t.Set.Contains(1), true) + gtest.Assert(t.Set.Contains(2), true) + gtest.Assert(t.Set.Contains(3), true) + gtest.Assert(t.Set.Contains(4), false) + }) +} diff --git a/container/gset/gset_z_unit_str_test.go b/container/gset/gset_z_unit_str_test.go index d1f95c401..9b9c69640 100644 --- a/container/gset/gset_z_unit_str_test.go +++ b/container/gset/gset_z_unit_str_test.go @@ -10,6 +10,8 @@ package gset_test import ( "encoding/json" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/util/gconv" "strings" "testing" @@ -360,3 +362,40 @@ func TestStrSet_AddIfNotExistFunc(t *testing.T) { gtest.Assert(s.Contains("4"), false) }) } + +func TestStrSet_UnmarshalValue(t *testing.T) { + type T struct { + Name string + Set *gset.StrSet + } + // JSON + gtest.Case(t, func() { + var t *T + err := gconv.Struct(g.Map{ + "name": "john", + "set": []byte(`["1","2","3"]`), + }, &t) + gtest.Assert(err, nil) + gtest.Assert(t.Name, "john") + gtest.Assert(t.Set.Size(), 3) + gtest.Assert(t.Set.Contains("1"), true) + gtest.Assert(t.Set.Contains("2"), true) + gtest.Assert(t.Set.Contains("3"), true) + gtest.Assert(t.Set.Contains("4"), false) + }) + // Map + gtest.Case(t, func() { + var t *T + err := gconv.Struct(g.Map{ + "name": "john", + "set": g.SliceStr{"1", "2", "3"}, + }, &t) + gtest.Assert(err, nil) + gtest.Assert(t.Name, "john") + gtest.Assert(t.Set.Size(), 3) + gtest.Assert(t.Set.Contains("1"), true) + gtest.Assert(t.Set.Contains("2"), true) + gtest.Assert(t.Set.Contains("3"), true) + gtest.Assert(t.Set.Contains("4"), false) + }) +} diff --git a/container/gtree/gtree_redblacktree.go b/container/gtree/gtree_redblacktree.go index 21b623cc2..0089f5a51 100644 --- a/container/gtree/gtree_redblacktree.go +++ b/container/gtree/gtree_redblacktree.go @@ -942,3 +942,17 @@ func (tree *RedBlackTree) UnmarshalJSON(b []byte) error { } return nil } + +// UnmarshalValue is an interface implement which sets any type of value for map. +func (tree *RedBlackTree) UnmarshalValue(value interface{}) (err error) { + if tree.mu == nil { + tree.mu = rwmutex.New() + tree.comparator = gutil.ComparatorString + } + tree.mu.Lock() + defer tree.mu.Unlock() + for k, v := range gconv.Map(value) { + tree.doSet(k, v) + } + return +} diff --git a/container/gtype/bool.go b/container/gtype/bool.go index 33edaa57f..f24fc8661 100644 --- a/container/gtype/bool.go +++ b/container/gtype/bool.go @@ -90,3 +90,9 @@ func (v *Bool) UnmarshalJSON(b []byte) error { v.Set(gconv.Bool(bytes.Trim(b, `"`))) return nil } + +// UnmarshalValue is an interface implement which sets any type of value for . +func (v *Bool) UnmarshalValue(value interface{}) error { + v.Set(gconv.Bool(value)) + return nil +} diff --git a/container/gtype/byte.go b/container/gtype/byte.go index 88f1fdcc1..0fdeb0ab4 100644 --- a/container/gtype/byte.go +++ b/container/gtype/byte.go @@ -68,3 +68,9 @@ func (v *Byte) UnmarshalJSON(b []byte) error { v.Set(gconv.Uint8(gconv.UnsafeBytesToStr(b))) return nil } + +// UnmarshalValue is an interface implement which sets any type of value for . +func (v *Byte) UnmarshalValue(value interface{}) error { + v.Set(gconv.Byte(value)) + return nil +} diff --git a/container/gtype/bytes.go b/container/gtype/bytes.go index a6cc7f219..75ae554b4 100644 --- a/container/gtype/bytes.go +++ b/container/gtype/bytes.go @@ -72,3 +72,9 @@ func (v *Bytes) UnmarshalJSON(b []byte) error { v.Set(src[:n]) return nil } + +// UnmarshalValue is an interface implement which sets any type of value for . +func (v *Bytes) UnmarshalValue(value interface{}) error { + v.Set(gconv.Bytes(value)) + return nil +} diff --git a/container/gtype/float32.go b/container/gtype/float32.go index 11e834c11..087a35d88 100644 --- a/container/gtype/float32.go +++ b/container/gtype/float32.go @@ -81,3 +81,9 @@ func (v *Float32) UnmarshalJSON(b []byte) error { v.Set(gconv.Float32(gconv.UnsafeBytesToStr(b))) return nil } + +// UnmarshalValue is an interface implement which sets any type of value for . +func (v *Float32) UnmarshalValue(value interface{}) error { + v.Set(gconv.Float32(value)) + return nil +} diff --git a/container/gtype/float64.go b/container/gtype/float64.go index 4c01f4208..749f1b622 100644 --- a/container/gtype/float64.go +++ b/container/gtype/float64.go @@ -81,3 +81,9 @@ func (v *Float64) UnmarshalJSON(b []byte) error { v.Set(gconv.Float64(gconv.UnsafeBytesToStr(b))) return nil } + +// UnmarshalValue is an interface implement which sets any type of value for . +func (v *Float64) UnmarshalValue(value interface{}) error { + v.Set(gconv.Float64(value)) + return nil +} diff --git a/container/gtype/int.go b/container/gtype/int.go index cf2ee6157..da649b946 100644 --- a/container/gtype/int.go +++ b/container/gtype/int.go @@ -68,3 +68,9 @@ func (v *Int) UnmarshalJSON(b []byte) error { v.Set(gconv.Int(gconv.UnsafeBytesToStr(b))) return nil } + +// UnmarshalValue is an interface implement which sets any type of value for . +func (v *Int) UnmarshalValue(value interface{}) error { + v.Set(gconv.Int(value)) + return nil +} diff --git a/container/gtype/int32.go b/container/gtype/int32.go index 4131184d5..75aba6adb 100644 --- a/container/gtype/int32.go +++ b/container/gtype/int32.go @@ -68,3 +68,9 @@ func (v *Int32) UnmarshalJSON(b []byte) error { v.Set(gconv.Int32(gconv.UnsafeBytesToStr(b))) return nil } + +// UnmarshalValue is an interface implement which sets any type of value for . +func (v *Int32) UnmarshalValue(value interface{}) error { + v.Set(gconv.Int32(value)) + return nil +} diff --git a/container/gtype/int64.go b/container/gtype/int64.go index 484d948bf..9d0f9448f 100644 --- a/container/gtype/int64.go +++ b/container/gtype/int64.go @@ -68,3 +68,9 @@ func (v *Int64) UnmarshalJSON(b []byte) error { v.Set(gconv.Int64(gconv.UnsafeBytesToStr(b))) return nil } + +// UnmarshalValue is an interface implement which sets any type of value for . +func (v *Int64) UnmarshalValue(value interface{}) error { + v.Set(gconv.Int64(value)) + return nil +} diff --git a/container/gtype/interface.go b/container/gtype/interface.go index f6550df28..c912f2657 100644 --- a/container/gtype/interface.go +++ b/container/gtype/interface.go @@ -65,3 +65,9 @@ func (v *Interface) UnmarshalJSON(b []byte) error { v.Set(i) return nil } + +// UnmarshalValue is an interface implement which sets any type of value for . +func (v *Interface) UnmarshalValue(value interface{}) error { + v.Set(value) + return nil +} diff --git a/container/gtype/string.go b/container/gtype/string.go index 3209ef6de..58798140d 100644 --- a/container/gtype/string.go +++ b/container/gtype/string.go @@ -63,3 +63,9 @@ func (v *String) UnmarshalJSON(b []byte) error { v.Set(gconv.UnsafeBytesToStr(bytes.Trim(b, `"`))) return nil } + +// UnmarshalValue is an interface implement which sets any type of value for . +func (v *String) UnmarshalValue(value interface{}) error { + v.Set(gconv.String(value)) + return nil +} diff --git a/container/gtype/uint.go b/container/gtype/uint.go index bb50ea6c8..d8802265d 100644 --- a/container/gtype/uint.go +++ b/container/gtype/uint.go @@ -68,3 +68,9 @@ func (v *Uint) UnmarshalJSON(b []byte) error { v.Set(gconv.Uint(gconv.UnsafeBytesToStr(b))) return nil } + +// UnmarshalValue is an interface implement which sets any type of value for . +func (v *Uint) UnmarshalValue(value interface{}) error { + v.Set(gconv.Uint(value)) + return nil +} diff --git a/container/gtype/uint32.go b/container/gtype/uint32.go index 5ef5bf2d6..403b7de59 100644 --- a/container/gtype/uint32.go +++ b/container/gtype/uint32.go @@ -68,3 +68,9 @@ func (v *Uint32) UnmarshalJSON(b []byte) error { v.Set(gconv.Uint32(gconv.UnsafeBytesToStr(b))) return nil } + +// UnmarshalValue is an interface implement which sets any type of value for . +func (v *Uint32) UnmarshalValue(value interface{}) error { + v.Set(gconv.Uint32(value)) + return nil +} diff --git a/container/gtype/uint64.go b/container/gtype/uint64.go index cede4aa6e..d3f8b36eb 100644 --- a/container/gtype/uint64.go +++ b/container/gtype/uint64.go @@ -68,3 +68,9 @@ func (v *Uint64) UnmarshalJSON(b []byte) error { v.Set(gconv.Uint64(gconv.UnsafeBytesToStr(b))) return nil } + +// UnmarshalValue is an interface implement which sets any type of value for . +func (v *Uint64) UnmarshalValue(value interface{}) error { + v.Set(gconv.Uint64(value)) + return nil +} diff --git a/container/gtype/z_unit_bool_test.go b/container/gtype/z_unit_bool_test.go new file mode 100644 index 000000000..2538a2e7e --- /dev/null +++ b/container/gtype/z_unit_bool_test.go @@ -0,0 +1,125 @@ +// Copyright 2018 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package gtype_test + +import ( + "encoding/json" + "github.com/gogf/gf/util/gconv" + "testing" + + "github.com/gogf/gf/container/gtype" + "github.com/gogf/gf/test/gtest" +) + +func Test_Bool(t *testing.T) { + gtest.Case(t, func() { + i := gtype.NewBool(true) + iClone := i.Clone() + gtest.AssertEQ(iClone.Set(false), true) + gtest.AssertEQ(iClone.Val(), false) + + i1 := gtype.NewBool(false) + iClone1 := i1.Clone() + gtest.AssertEQ(iClone1.Set(true), false) + gtest.AssertEQ(iClone1.Val(), true) + + //空参测试 + i2 := gtype.NewBool() + gtest.AssertEQ(i2.Val(), false) + }) +} + +func Test_Bool_JSON(t *testing.T) { + // Marshal + gtest.Case(t, func() { + i := gtype.NewBool(true) + b1, err1 := json.Marshal(i) + b2, err2 := json.Marshal(i.Val()) + gtest.Assert(err1, nil) + gtest.Assert(err2, nil) + gtest.Assert(b1, b2) + }) + gtest.Case(t, func() { + i := gtype.NewBool(false) + b1, err1 := json.Marshal(i) + b2, err2 := json.Marshal(i.Val()) + gtest.Assert(err1, nil) + gtest.Assert(err2, nil) + gtest.Assert(b1, b2) + }) + // Unmarshal + gtest.Case(t, func() { + var err error + i := gtype.NewBool() + err = json.Unmarshal([]byte("true"), &i) + gtest.Assert(err, nil) + gtest.Assert(i.Val(), true) + err = json.Unmarshal([]byte("false"), &i) + gtest.Assert(err, nil) + gtest.Assert(i.Val(), false) + err = json.Unmarshal([]byte("1"), &i) + gtest.Assert(err, nil) + gtest.Assert(i.Val(), true) + err = json.Unmarshal([]byte("0"), &i) + gtest.Assert(err, nil) + gtest.Assert(i.Val(), false) + }) + + gtest.Case(t, func() { + i := gtype.NewBool(true) + b1, err1 := json.Marshal(i) + b2, err2 := json.Marshal(i.Val()) + gtest.Assert(err1, nil) + gtest.Assert(err2, nil) + gtest.Assert(b1, b2) + + i2 := gtype.NewBool() + err := json.Unmarshal(b2, &i2) + gtest.Assert(err, nil) + gtest.Assert(i2.Val(), i.Val()) + }) + gtest.Case(t, func() { + i := gtype.NewBool(false) + b1, err1 := json.Marshal(i) + b2, err2 := json.Marshal(i.Val()) + gtest.Assert(err1, nil) + gtest.Assert(err2, nil) + gtest.Assert(b1, b2) + + i2 := gtype.NewBool() + err := json.Unmarshal(b2, &i2) + gtest.Assert(err, nil) + gtest.Assert(i2.Val(), i.Val()) + }) +} + +func Test_Bool_UnmarshalValue(t *testing.T) { + type T struct { + Name string + Var *gtype.Bool + } + gtest.Case(t, func() { + var t *T + err := gconv.Struct(map[string]interface{}{ + "name": "john", + "var": "true", + }, &t) + gtest.Assert(err, nil) + gtest.Assert(t.Name, "john") + gtest.Assert(t.Var.Val(), true) + }) + gtest.Case(t, func() { + var t *T + err := gconv.Struct(map[string]interface{}{ + "name": "john", + "var": "false", + }, &t) + gtest.Assert(err, nil) + gtest.Assert(t.Name, "john") + gtest.Assert(t.Var.Val(), false) + }) +} diff --git a/container/gtype/z_unit_byte_test.go b/container/gtype/z_unit_byte_test.go new file mode 100644 index 000000000..55e7c92c5 --- /dev/null +++ b/container/gtype/z_unit_byte_test.go @@ -0,0 +1,77 @@ +// Copyright 2018 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package gtype_test + +import ( + "encoding/json" + "github.com/gogf/gf/util/gconv" + "sync" + "testing" + + "github.com/gogf/gf/container/gtype" + "github.com/gogf/gf/test/gtest" +) + +func Test_Byte(t *testing.T) { + gtest.Case(t, func() { + var wg sync.WaitGroup + addTimes := 127 + i := gtype.NewByte(byte(0)) + iClone := i.Clone() + gtest.AssertEQ(iClone.Set(byte(1)), byte(0)) + gtest.AssertEQ(iClone.Val(), byte(1)) + for index := 0; index < addTimes; index++ { + wg.Add(1) + go func() { + defer wg.Done() + i.Add(1) + }() + } + wg.Wait() + gtest.AssertEQ(byte(addTimes), i.Val()) + + //空参测试 + i1 := gtype.NewByte() + gtest.AssertEQ(i1.Val(), byte(0)) + }) +} + +func Test_Byte_JSON(t *testing.T) { + gtest.Case(t, func() { + i := gtype.NewByte(49) + b1, err1 := json.Marshal(i) + b2, err2 := json.Marshal(i.Val()) + gtest.Assert(err1, nil) + gtest.Assert(err2, nil) + gtest.Assert(b1, b2) + }) + // Unmarshal + gtest.Case(t, func() { + var err error + i := gtype.NewByte() + err = json.Unmarshal([]byte("49"), &i) + gtest.Assert(err, nil) + gtest.Assert(i.Val(), "49") + }) +} + +func Test_Byte_UnmarshalValue(t *testing.T) { + type T struct { + Name string + Var *gtype.Byte + } + gtest.Case(t, func() { + var t *T + err := gconv.Struct(map[string]interface{}{ + "name": "john", + "var": "2", + }, &t) + gtest.Assert(err, nil) + gtest.Assert(t.Name, "john") + gtest.Assert(t.Var.Val(), "2") + }) +} diff --git a/container/gtype/z_unit_bytes_test.go b/container/gtype/z_unit_bytes_test.go new file mode 100644 index 000000000..71f0690c0 --- /dev/null +++ b/container/gtype/z_unit_bytes_test.go @@ -0,0 +1,63 @@ +// Copyright 2018 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package gtype_test + +import ( + "encoding/json" + "github.com/gogf/gf/util/gconv" + "testing" + + "github.com/gogf/gf/container/gtype" + "github.com/gogf/gf/test/gtest" +) + +func Test_Bytes(t *testing.T) { + gtest.Case(t, func() { + i := gtype.NewBytes([]byte("abc")) + iClone := i.Clone() + gtest.AssertEQ(iClone.Set([]byte("123")), []byte("abc")) + gtest.AssertEQ(iClone.Val(), []byte("123")) + + //空参测试 + i1 := gtype.NewBytes() + gtest.AssertEQ(i1.Val(), nil) + }) +} + +func Test_Bytes_JSON(t *testing.T) { + gtest.Case(t, func() { + b := []byte("i love gf") + i := gtype.NewBytes(b) + b1, err1 := json.Marshal(i) + b2, err2 := json.Marshal(i.Val()) + gtest.Assert(err1, nil) + gtest.Assert(err2, nil) + gtest.Assert(b1, b2) + + i2 := gtype.NewBytes() + err := json.Unmarshal(b2, &i2) + gtest.Assert(err, nil) + gtest.Assert(i2.Val(), b) + }) +} + +func Test_Bytes_UnmarshalValue(t *testing.T) { + type T struct { + Name string + Var *gtype.Bytes + } + gtest.Case(t, func() { + var t *T + err := gconv.Struct(map[string]interface{}{ + "name": "john", + "var": "123", + }, &t) + gtest.Assert(err, nil) + gtest.Assert(t.Name, "john") + gtest.Assert(t.Var.Val(), "123") + }) +} diff --git a/container/gtype/z_unit_float32_test.go b/container/gtype/z_unit_float32_test.go new file mode 100644 index 000000000..5383cd7ff --- /dev/null +++ b/container/gtype/z_unit_float32_test.go @@ -0,0 +1,64 @@ +// Copyright 2018 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package gtype_test + +import ( + "encoding/json" + "github.com/gogf/gf/container/gtype" + "github.com/gogf/gf/test/gtest" + "github.com/gogf/gf/util/gconv" + "math" + "testing" +) + +func Test_Float32(t *testing.T) { + gtest.Case(t, func() { + i := gtype.NewFloat32(0) + iClone := i.Clone() + gtest.AssertEQ(iClone.Set(0.1), float32(0)) + gtest.AssertEQ(iClone.Val(), float32(0.1)) + + //空参测试 + i1 := gtype.NewFloat32() + gtest.AssertEQ(i1.Val(), float32(0)) + }) +} + +func Test_Float32_JSON(t *testing.T) { + gtest.Case(t, func() { + v := float32(math.MaxFloat32) + i := gtype.NewFloat32(v) + b1, err1 := json.Marshal(i) + b2, err2 := json.Marshal(i.Val()) + + gtest.Assert(err1, nil) + gtest.Assert(err2, nil) + gtest.Assert(b1, b2) + + i2 := gtype.NewFloat32() + err := json.Unmarshal(b2, &i2) + gtest.Assert(err, nil) + gtest.Assert(i2.Val(), v) + }) +} + +func Test_Float32_UnmarshalValue(t *testing.T) { + type T struct { + Name string + Var *gtype.Float32 + } + gtest.Case(t, func() { + var t *T + err := gconv.Struct(map[string]interface{}{ + "name": "john", + "var": "123.456", + }, &t) + gtest.Assert(err, nil) + gtest.Assert(t.Name, "john") + gtest.Assert(t.Var.Val(), "123.456") + }) +} diff --git a/container/gtype/z_unit_float64_test.go b/container/gtype/z_unit_float64_test.go new file mode 100644 index 000000000..480c01df3 --- /dev/null +++ b/container/gtype/z_unit_float64_test.go @@ -0,0 +1,62 @@ +// Copyright 2018 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package gtype_test + +import ( + "encoding/json" + "github.com/gogf/gf/container/gtype" + "github.com/gogf/gf/test/gtest" + "github.com/gogf/gf/util/gconv" + "math" + "testing" +) + +func Test_Float64(t *testing.T) { + gtest.Case(t, func() { + i := gtype.NewFloat64(0) + iClone := i.Clone() + gtest.AssertEQ(iClone.Set(0.1), float64(0)) + gtest.AssertEQ(iClone.Val(), float64(0.1)) + //空参测试 + i1 := gtype.NewFloat64() + gtest.AssertEQ(i1.Val(), float64(0)) + }) +} + +func Test_Float64_JSON(t *testing.T) { + gtest.Case(t, func() { + v := math.MaxFloat64 + i := gtype.NewFloat64(v) + b1, err1 := json.Marshal(i) + b2, err2 := json.Marshal(i.Val()) + gtest.Assert(err1, nil) + gtest.Assert(err2, nil) + gtest.Assert(b1, b2) + + i2 := gtype.NewFloat64() + err := json.Unmarshal(b2, &i2) + gtest.Assert(err, nil) + gtest.Assert(i2.Val(), v) + }) +} + +func Test_Float64_UnmarshalValue(t *testing.T) { + type T struct { + Name string + Var *gtype.Float64 + } + gtest.Case(t, func() { + var t *T + err := gconv.Struct(map[string]interface{}{ + "name": "john", + "var": "123.456", + }, &t) + gtest.Assert(err, nil) + gtest.Assert(t.Name, "john") + gtest.Assert(t.Var.Val(), "123.456") + }) +} diff --git a/container/gtype/z_unit_int32_test.go b/container/gtype/z_unit_int32_test.go new file mode 100644 index 000000000..4870da7a2 --- /dev/null +++ b/container/gtype/z_unit_int32_test.go @@ -0,0 +1,75 @@ +// Copyright 2018 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package gtype_test + +import ( + "encoding/json" + "github.com/gogf/gf/container/gtype" + "github.com/gogf/gf/test/gtest" + "github.com/gogf/gf/util/gconv" + "math" + "sync" + "testing" +) + +func Test_Int32(t *testing.T) { + gtest.Case(t, func() { + var wg sync.WaitGroup + addTimes := 1000 + i := gtype.NewInt32(0) + iClone := i.Clone() + gtest.AssertEQ(iClone.Set(1), int32(0)) + gtest.AssertEQ(iClone.Val(), int32(1)) + for index := 0; index < addTimes; index++ { + wg.Add(1) + go func() { + defer wg.Done() + i.Add(1) + }() + } + wg.Wait() + gtest.AssertEQ(int32(addTimes), i.Val()) + + //空参测试 + i1 := gtype.NewInt32() + gtest.AssertEQ(i1.Val(), int32(0)) + }) +} + +func Test_Int32_JSON(t *testing.T) { + gtest.Case(t, func() { + v := int32(math.MaxInt32) + i := gtype.NewInt32(v) + b1, err1 := json.Marshal(i) + b2, err2 := json.Marshal(i.Val()) + gtest.Assert(err1, nil) + gtest.Assert(err2, nil) + gtest.Assert(b1, b2) + + i2 := gtype.NewInt32() + err := json.Unmarshal(b2, &i2) + gtest.Assert(err, nil) + gtest.Assert(i2.Val(), v) + }) +} + +func Test_Int32_UnmarshalValue(t *testing.T) { + type T struct { + Name string + Var *gtype.Int32 + } + gtest.Case(t, func() { + var t *T + err := gconv.Struct(map[string]interface{}{ + "name": "john", + "var": "123", + }, &t) + gtest.Assert(err, nil) + gtest.Assert(t.Name, "john") + gtest.Assert(t.Var.Val(), "123") + }) +} diff --git a/container/gtype/z_unit_int64_test.go b/container/gtype/z_unit_int64_test.go new file mode 100644 index 000000000..059f4ca2c --- /dev/null +++ b/container/gtype/z_unit_int64_test.go @@ -0,0 +1,74 @@ +// Copyright 2018 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package gtype_test + +import ( + "encoding/json" + "github.com/gogf/gf/container/gtype" + "github.com/gogf/gf/test/gtest" + "github.com/gogf/gf/util/gconv" + "math" + "sync" + "testing" +) + +func Test_Int64(t *testing.T) { + gtest.Case(t, func() { + var wg sync.WaitGroup + addTimes := 1000 + i := gtype.NewInt64(0) + iClone := i.Clone() + gtest.AssertEQ(iClone.Set(1), int64(0)) + gtest.AssertEQ(iClone.Val(), int64(1)) + for index := 0; index < addTimes; index++ { + wg.Add(1) + go func() { + defer wg.Done() + i.Add(1) + }() + } + wg.Wait() + gtest.AssertEQ(int64(addTimes), i.Val()) + + //空参测试 + i1 := gtype.NewInt64() + gtest.AssertEQ(i1.Val(), int64(0)) + }) +} + +func Test_Int64_JSON(t *testing.T) { + gtest.Case(t, func() { + i := gtype.NewInt64(math.MaxInt64) + b1, err1 := json.Marshal(i) + b2, err2 := json.Marshal(i.Val()) + gtest.Assert(err1, nil) + gtest.Assert(err2, nil) + gtest.Assert(b1, b2) + + i2 := gtype.NewInt64() + err := json.Unmarshal(b2, &i2) + gtest.Assert(err, nil) + gtest.Assert(i2.Val(), i) + }) +} + +func Test_Int64_UnmarshalValue(t *testing.T) { + type T struct { + Name string + Var *gtype.Int64 + } + gtest.Case(t, func() { + var t *T + err := gconv.Struct(map[string]interface{}{ + "name": "john", + "var": "123", + }, &t) + gtest.Assert(err, nil) + gtest.Assert(t.Name, "john") + gtest.Assert(t.Var.Val(), "123") + }) +} diff --git a/container/gtype/z_unit_int_test.go b/container/gtype/z_unit_int_test.go new file mode 100644 index 000000000..bd13b8b60 --- /dev/null +++ b/container/gtype/z_unit_int_test.go @@ -0,0 +1,74 @@ +// Copyright 2018 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package gtype_test + +import ( + "encoding/json" + "github.com/gogf/gf/container/gtype" + "github.com/gogf/gf/test/gtest" + "github.com/gogf/gf/util/gconv" + "sync" + "testing" +) + +func Test_Int(t *testing.T) { + gtest.Case(t, func() { + var wg sync.WaitGroup + addTimes := 1000 + i := gtype.NewInt(0) + iClone := i.Clone() + gtest.AssertEQ(iClone.Set(1), 0) + gtest.AssertEQ(iClone.Val(), 1) + for index := 0; index < addTimes; index++ { + wg.Add(1) + go func() { + defer wg.Done() + i.Add(1) + }() + } + wg.Wait() + gtest.AssertEQ(addTimes, i.Val()) + + //空参测试 + i1 := gtype.NewInt() + gtest.AssertEQ(i1.Val(), 0) + }) +} + +func Test_Int_JSON(t *testing.T) { + gtest.Case(t, func() { + v := 666 + i := gtype.NewInt(v) + b1, err1 := json.Marshal(i) + b2, err2 := json.Marshal(i.Val()) + gtest.Assert(err1, nil) + gtest.Assert(err2, nil) + gtest.Assert(b1, b2) + + i2 := gtype.NewInt() + err := json.Unmarshal(b2, &i2) + gtest.Assert(err, nil) + gtest.Assert(i2.Val(), v) + }) +} + +func Test_Int_UnmarshalValue(t *testing.T) { + type T struct { + Name string + Var *gtype.Int + } + gtest.Case(t, func() { + var t *T + err := gconv.Struct(map[string]interface{}{ + "name": "john", + "var": "123", + }, &t) + gtest.Assert(err, nil) + gtest.Assert(t.Name, "john") + gtest.Assert(t.Var.Val(), "123") + }) +} diff --git a/container/gtype/z_unit_interface_test.go b/container/gtype/z_unit_interface_test.go new file mode 100644 index 000000000..1f9af3bfb --- /dev/null +++ b/container/gtype/z_unit_interface_test.go @@ -0,0 +1,64 @@ +// Copyright 2018 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package gtype_test + +import ( + "encoding/json" + "github.com/gogf/gf/container/gtype" + "github.com/gogf/gf/test/gtest" + "github.com/gogf/gf/util/gconv" + "testing" +) + +func Test_Interface(t *testing.T) { + gtest.Case(t, func() { + t := Temp{Name: "gf", Age: 18} + t1 := Temp{Name: "gf", Age: 19} + i := gtype.New(t) + iClone := i.Clone() + gtest.AssertEQ(iClone.Set(t1), t) + gtest.AssertEQ(iClone.Val().(Temp), t1) + + //空参测试 + i1 := gtype.New() + gtest.AssertEQ(i1.Val(), nil) + }) +} + +func Test_Interface_JSON(t *testing.T) { + gtest.Case(t, func() { + s := "i love gf" + i := gtype.New(s) + b1, err1 := json.Marshal(i) + b2, err2 := json.Marshal(i.Val()) + gtest.Assert(err1, nil) + gtest.Assert(err2, nil) + gtest.Assert(b1, b2) + + i2 := gtype.New() + err := json.Unmarshal(b2, &i2) + gtest.Assert(err, nil) + gtest.Assert(i2.Val(), s) + }) +} + +func Test_Interface_UnmarshalValue(t *testing.T) { + type T struct { + Name string + Var *gtype.Interface + } + gtest.Case(t, func() { + var t *T + err := gconv.Struct(map[string]interface{}{ + "name": "john", + "var": "123", + }, &t) + gtest.Assert(err, nil) + gtest.Assert(t.Name, "john") + gtest.Assert(t.Var.Val(), "123") + }) +} diff --git a/container/gtype/z_unit_string_test.go b/container/gtype/z_unit_string_test.go new file mode 100644 index 000000000..7d010c64c --- /dev/null +++ b/container/gtype/z_unit_string_test.go @@ -0,0 +1,62 @@ +// Copyright 2018 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package gtype_test + +import ( + "encoding/json" + "github.com/gogf/gf/container/gtype" + "github.com/gogf/gf/test/gtest" + "github.com/gogf/gf/util/gconv" + "testing" +) + +func Test_String(t *testing.T) { + gtest.Case(t, func() { + i := gtype.NewString("abc") + iClone := i.Clone() + gtest.AssertEQ(iClone.Set("123"), "abc") + gtest.AssertEQ(iClone.Val(), "123") + + //空参测试 + i1 := gtype.NewString() + gtest.AssertEQ(i1.Val(), "") + }) +} + +func Test_String_JSON(t *testing.T) { + gtest.Case(t, func() { + s := "i love gf" + i1 := gtype.NewString(s) + b1, err1 := json.Marshal(i1) + b2, err2 := json.Marshal(i1.Val()) + gtest.Assert(err1, nil) + gtest.Assert(err2, nil) + gtest.Assert(b1, b2) + + i2 := gtype.NewString() + err := json.Unmarshal(b2, &i2) + gtest.Assert(err, nil) + gtest.Assert(i2.Val(), s) + }) +} + +func Test_String_UnmarshalValue(t *testing.T) { + type T struct { + Name string + Var *gtype.String + } + gtest.Case(t, func() { + var t *T + err := gconv.Struct(map[string]interface{}{ + "name": "john", + "var": "123", + }, &t) + gtest.Assert(err, nil) + gtest.Assert(t.Name, "john") + gtest.Assert(t.Var.Val(), "123") + }) +} diff --git a/container/gtype/z_unit_test.go b/container/gtype/z_unit_test.go deleted file mode 100644 index 78d1d0833..000000000 --- a/container/gtype/z_unit_test.go +++ /dev/null @@ -1,528 +0,0 @@ -// Copyright 2018 gf Author(https://github.com/gogf/gf). All Rights Reserved. -// -// This Source Code Form is subject to the terms of the MIT License. -// If a copy of the MIT was not distributed with this file, -// You can obtain one at https://github.com/gogf/gf. - -package gtype_test - -import ( - "encoding/json" - "math" - "sync" - "testing" - - "github.com/gogf/gf/container/gtype" - "github.com/gogf/gf/test/gtest" -) - -type Temp struct { - Name string - Age int -} - -func Test_Bool(t *testing.T) { - gtest.Case(t, func() { - i := gtype.NewBool(true) - iClone := i.Clone() - gtest.AssertEQ(iClone.Set(false), true) - gtest.AssertEQ(iClone.Val(), false) - - i1 := gtype.NewBool(false) - iClone1 := i1.Clone() - gtest.AssertEQ(iClone1.Set(true), false) - gtest.AssertEQ(iClone1.Val(), true) - - //空参测试 - i2 := gtype.NewBool() - gtest.AssertEQ(i2.Val(), false) - }) - - // Marshal - gtest.Case(t, func() { - i := gtype.NewBool(true) - b1, err1 := json.Marshal(i) - b2, err2 := json.Marshal(i.Val()) - gtest.Assert(err1, nil) - gtest.Assert(err2, nil) - gtest.Assert(b1, b2) - }) - gtest.Case(t, func() { - i := gtype.NewBool(false) - b1, err1 := json.Marshal(i) - b2, err2 := json.Marshal(i.Val()) - gtest.Assert(err1, nil) - gtest.Assert(err2, nil) - gtest.Assert(b1, b2) - }) - // Unmarshal - gtest.Case(t, func() { - var err error - i := gtype.NewBool() - err = json.Unmarshal([]byte("true"), &i) - gtest.Assert(err, nil) - gtest.Assert(i.Val(), true) - err = json.Unmarshal([]byte("false"), &i) - gtest.Assert(err, nil) - gtest.Assert(i.Val(), false) - err = json.Unmarshal([]byte("1"), &i) - gtest.Assert(err, nil) - gtest.Assert(i.Val(), true) - err = json.Unmarshal([]byte("0"), &i) - gtest.Assert(err, nil) - gtest.Assert(i.Val(), false) - }) - - gtest.Case(t, func() { - i := gtype.NewBool(true) - b1, err1 := json.Marshal(i) - b2, err2 := json.Marshal(i.Val()) - gtest.Assert(err1, nil) - gtest.Assert(err2, nil) - gtest.Assert(b1, b2) - - i2 := gtype.NewBool() - err := json.Unmarshal(b2, &i2) - gtest.Assert(err, nil) - gtest.Assert(i2.Val(), i.Val()) - }) - gtest.Case(t, func() { - i := gtype.NewBool(false) - b1, err1 := json.Marshal(i) - b2, err2 := json.Marshal(i.Val()) - gtest.Assert(err1, nil) - gtest.Assert(err2, nil) - gtest.Assert(b1, b2) - - i2 := gtype.NewBool() - err := json.Unmarshal(b2, &i2) - gtest.Assert(err, nil) - gtest.Assert(i2.Val(), i.Val()) - }) -} - -func Test_Byte(t *testing.T) { - gtest.Case(t, func() { - var wg sync.WaitGroup - addTimes := 127 - i := gtype.NewByte(byte(0)) - iClone := i.Clone() - gtest.AssertEQ(iClone.Set(byte(1)), byte(0)) - gtest.AssertEQ(iClone.Val(), byte(1)) - for index := 0; index < addTimes; index++ { - wg.Add(1) - go func() { - defer wg.Done() - i.Add(1) - }() - } - wg.Wait() - gtest.AssertEQ(byte(addTimes), i.Val()) - - //空参测试 - i1 := gtype.NewByte() - gtest.AssertEQ(i1.Val(), byte(0)) - }) - gtest.Case(t, func() { - i := gtype.NewByte(49) - b1, err1 := json.Marshal(i) - b2, err2 := json.Marshal(i.Val()) - gtest.Assert(err1, nil) - gtest.Assert(err2, nil) - gtest.Assert(b1, b2) - }) - // Unmarshal - gtest.Case(t, func() { - var err error - i := gtype.NewByte() - err = json.Unmarshal([]byte("49"), &i) - gtest.Assert(err, nil) - gtest.Assert(i.Val(), "49") - }) -} - -func Test_Bytes(t *testing.T) { - gtest.Case(t, func() { - i := gtype.NewBytes([]byte("abc")) - iClone := i.Clone() - gtest.AssertEQ(iClone.Set([]byte("123")), []byte("abc")) - gtest.AssertEQ(iClone.Val(), []byte("123")) - - //空参测试 - i1 := gtype.NewBytes() - gtest.AssertEQ(i1.Val(), nil) - }) - gtest.Case(t, func() { - b := []byte("i love gf") - i := gtype.NewBytes(b) - b1, err1 := json.Marshal(i) - b2, err2 := json.Marshal(i.Val()) - gtest.Assert(err1, nil) - gtest.Assert(err2, nil) - gtest.Assert(b1, b2) - - i2 := gtype.NewBytes() - err := json.Unmarshal(b2, &i2) - gtest.Assert(err, nil) - gtest.Assert(i2.Val(), b) - }) -} - -func Test_String(t *testing.T) { - gtest.Case(t, func() { - i := gtype.NewString("abc") - iClone := i.Clone() - gtest.AssertEQ(iClone.Set("123"), "abc") - gtest.AssertEQ(iClone.Val(), "123") - - //空参测试 - i1 := gtype.NewString() - gtest.AssertEQ(i1.Val(), "") - }) - gtest.Case(t, func() { - s := "i love gf" - i1 := gtype.NewString(s) - b1, err1 := json.Marshal(i1) - b2, err2 := json.Marshal(i1.Val()) - gtest.Assert(err1, nil) - gtest.Assert(err2, nil) - gtest.Assert(b1, b2) - - i2 := gtype.NewString() - err := json.Unmarshal(b2, &i2) - gtest.Assert(err, nil) - gtest.Assert(i2.Val(), s) - }) -} - -func Test_Interface(t *testing.T) { - gtest.Case(t, func() { - t := Temp{Name: "gf", Age: 18} - t1 := Temp{Name: "gf", Age: 19} - i := gtype.New(t) - iClone := i.Clone() - gtest.AssertEQ(iClone.Set(t1), t) - gtest.AssertEQ(iClone.Val().(Temp), t1) - - //空参测试 - i1 := gtype.New() - gtest.AssertEQ(i1.Val(), nil) - }) - gtest.Case(t, func() { - s := "i love gf" - i := gtype.New(s) - b1, err1 := json.Marshal(i) - b2, err2 := json.Marshal(i.Val()) - gtest.Assert(err1, nil) - gtest.Assert(err2, nil) - gtest.Assert(b1, b2) - - i2 := gtype.New() - err := json.Unmarshal(b2, &i2) - gtest.Assert(err, nil) - gtest.Assert(i2.Val(), s) - }) -} - -func Test_Float32(t *testing.T) { - gtest.Case(t, func() { - //var wg sync.WaitGroup - //addTimes := 100 - i := gtype.NewFloat32(0) - iClone := i.Clone() - gtest.AssertEQ(iClone.Set(0.1), float32(0)) - gtest.AssertEQ(iClone.Val(), float32(0.1)) - // for index := 0; index < addTimes; index++ { - // wg.Add(1) - // go func() { - // defer wg.Done() - // i.Add(0.2) - // fmt.Println(i.Val()) - // }() - // } - // wg.Wait() - // gtest.AssertEQ(100.0, i.Val()) - - //空参测试 - i1 := gtype.NewFloat32() - gtest.AssertEQ(i1.Val(), float32(0)) - }) - gtest.Case(t, func() { - v := float32(math.MaxFloat32) - i := gtype.NewFloat32(v) - b1, err1 := json.Marshal(i) - b2, err2 := json.Marshal(i.Val()) - - gtest.Assert(err1, nil) - gtest.Assert(err2, nil) - gtest.Assert(b1, b2) - - i2 := gtype.NewFloat32() - err := json.Unmarshal(b2, &i2) - gtest.Assert(err, nil) - gtest.Assert(i2.Val(), v) - }) -} - -func Test_Float64(t *testing.T) { - gtest.Case(t, func() { - //var wg sync.WaitGroup - //addTimes := 100 - i := gtype.NewFloat64(0) - iClone := i.Clone() - gtest.AssertEQ(iClone.Set(0.1), float64(0)) - gtest.AssertEQ(iClone.Val(), float64(0.1)) - // for index := 0; index < addTimes; index++ { - // wg.Add(1) - // go func() { - // defer wg.Done() - // i.Add(0.1) - // fmt.Println(i.Val()) - // }() - // } - // wg.Wait() - // gtest.AssertEQ(100.0, i.Val()) - - //空参测试 - i1 := gtype.NewFloat64() - gtest.AssertEQ(i1.Val(), float64(0)) - }) - gtest.Case(t, func() { - v := math.MaxFloat64 - i := gtype.NewFloat64(v) - b1, err1 := json.Marshal(i) - b2, err2 := json.Marshal(i.Val()) - gtest.Assert(err1, nil) - gtest.Assert(err2, nil) - gtest.Assert(b1, b2) - - i2 := gtype.NewFloat64() - err := json.Unmarshal(b2, &i2) - gtest.Assert(err, nil) - gtest.Assert(i2.Val(), v) - }) -} - -func Test_Int(t *testing.T) { - gtest.Case(t, func() { - var wg sync.WaitGroup - addTimes := 1000 - i := gtype.NewInt(0) - iClone := i.Clone() - gtest.AssertEQ(iClone.Set(1), 0) - gtest.AssertEQ(iClone.Val(), 1) - for index := 0; index < addTimes; index++ { - wg.Add(1) - go func() { - defer wg.Done() - i.Add(1) - }() - } - wg.Wait() - gtest.AssertEQ(addTimes, i.Val()) - - //空参测试 - i1 := gtype.NewInt() - gtest.AssertEQ(i1.Val(), 0) - }) - gtest.Case(t, func() { - v := 666 - i := gtype.NewInt(v) - b1, err1 := json.Marshal(i) - b2, err2 := json.Marshal(i.Val()) - gtest.Assert(err1, nil) - gtest.Assert(err2, nil) - gtest.Assert(b1, b2) - - i2 := gtype.NewInt() - err := json.Unmarshal(b2, &i2) - gtest.Assert(err, nil) - gtest.Assert(i2.Val(), v) - }) -} - -func Test_Int32(t *testing.T) { - gtest.Case(t, func() { - var wg sync.WaitGroup - addTimes := 1000 - i := gtype.NewInt32(0) - iClone := i.Clone() - gtest.AssertEQ(iClone.Set(1), int32(0)) - gtest.AssertEQ(iClone.Val(), int32(1)) - for index := 0; index < addTimes; index++ { - wg.Add(1) - go func() { - defer wg.Done() - i.Add(1) - }() - } - wg.Wait() - gtest.AssertEQ(int32(addTimes), i.Val()) - - //空参测试 - i1 := gtype.NewInt32() - gtest.AssertEQ(i1.Val(), int32(0)) - }) - gtest.Case(t, func() { - v := int32(math.MaxInt32) - i := gtype.NewInt32(v) - b1, err1 := json.Marshal(i) - b2, err2 := json.Marshal(i.Val()) - gtest.Assert(err1, nil) - gtest.Assert(err2, nil) - gtest.Assert(b1, b2) - - i2 := gtype.NewInt32() - err := json.Unmarshal(b2, &i2) - gtest.Assert(err, nil) - gtest.Assert(i2.Val(), v) - }) -} - -func Test_Int64(t *testing.T) { - gtest.Case(t, func() { - var wg sync.WaitGroup - addTimes := 1000 - i := gtype.NewInt64(0) - iClone := i.Clone() - gtest.AssertEQ(iClone.Set(1), int64(0)) - gtest.AssertEQ(iClone.Val(), int64(1)) - for index := 0; index < addTimes; index++ { - wg.Add(1) - go func() { - defer wg.Done() - i.Add(1) - }() - } - wg.Wait() - gtest.AssertEQ(int64(addTimes), i.Val()) - - //空参测试 - i1 := gtype.NewInt64() - gtest.AssertEQ(i1.Val(), int64(0)) - }) - gtest.Case(t, func() { - i := gtype.NewInt64(math.MaxInt64) - b1, err1 := json.Marshal(i) - b2, err2 := json.Marshal(i.Val()) - gtest.Assert(err1, nil) - gtest.Assert(err2, nil) - gtest.Assert(b1, b2) - - i2 := gtype.NewInt64() - err := json.Unmarshal(b2, &i2) - gtest.Assert(err, nil) - gtest.Assert(i2.Val(), i) - }) -} - -func Test_Uint(t *testing.T) { - gtest.Case(t, func() { - var wg sync.WaitGroup - addTimes := 1000 - i := gtype.NewUint(0) - iClone := i.Clone() - gtest.AssertEQ(iClone.Set(1), uint(0)) - gtest.AssertEQ(iClone.Val(), uint(1)) - for index := 0; index < addTimes; index++ { - wg.Add(1) - go func() { - defer wg.Done() - i.Add(1) - }() - } - wg.Wait() - gtest.AssertEQ(uint(addTimes), i.Val()) - - //空参测试 - i1 := gtype.NewUint() - gtest.AssertEQ(i1.Val(), uint(0)) - }) - gtest.Case(t, func() { - i := gtype.NewUint(666) - b1, err1 := json.Marshal(i) - b2, err2 := json.Marshal(i.Val()) - gtest.Assert(err1, nil) - gtest.Assert(err2, nil) - gtest.Assert(b1, b2) - - i2 := gtype.NewUint() - err := json.Unmarshal(b2, &i2) - gtest.Assert(err, nil) - gtest.Assert(i2.Val(), i) - }) -} - -func Test_Uint32(t *testing.T) { - gtest.Case(t, func() { - var wg sync.WaitGroup - addTimes := 1000 - i := gtype.NewUint32(0) - iClone := i.Clone() - gtest.AssertEQ(iClone.Set(1), uint32(0)) - gtest.AssertEQ(iClone.Val(), uint32(1)) - for index := 0; index < addTimes; index++ { - wg.Add(1) - go func() { - defer wg.Done() - i.Add(1) - }() - } - wg.Wait() - gtest.AssertEQ(uint32(addTimes), i.Val()) - - //空参测试 - i1 := gtype.NewUint32() - gtest.AssertEQ(i1.Val(), uint32(0)) - }) - gtest.Case(t, func() { - i := gtype.NewUint32(math.MaxUint32) - b1, err1 := json.Marshal(i) - b2, err2 := json.Marshal(i.Val()) - gtest.Assert(err1, nil) - gtest.Assert(err2, nil) - gtest.Assert(b1, b2) - - i2 := gtype.NewUint32() - err := json.Unmarshal(b2, &i2) - gtest.Assert(err, nil) - gtest.Assert(i2.Val(), i) - }) -} - -func Test_Uint64(t *testing.T) { - gtest.Case(t, func() { - var wg sync.WaitGroup - addTimes := 1000 - i := gtype.NewUint64(0) - iClone := i.Clone() - gtest.AssertEQ(iClone.Set(1), uint64(0)) - gtest.AssertEQ(iClone.Val(), uint64(1)) - for index := 0; index < addTimes; index++ { - wg.Add(1) - go func() { - defer wg.Done() - i.Add(1) - }() - } - wg.Wait() - gtest.AssertEQ(uint64(addTimes), i.Val()) - - //空参测试 - i1 := gtype.NewUint64() - gtest.AssertEQ(i1.Val(), uint64(0)) - }) - gtest.Case(t, func() { - i := gtype.NewUint64(math.MaxUint64) - b1, err1 := json.Marshal(i) - b2, err2 := json.Marshal(i.Val()) - gtest.Assert(err1, nil) - gtest.Assert(err2, nil) - gtest.Assert(b1, b2) - - i2 := gtype.NewUint64() - err := json.Unmarshal(b2, &i2) - gtest.Assert(err, nil) - gtest.Assert(i2.Val(), i) - }) -} diff --git a/container/gtype/z_unit_uint32_test.go b/container/gtype/z_unit_uint32_test.go new file mode 100644 index 000000000..a58cc5656 --- /dev/null +++ b/container/gtype/z_unit_uint32_test.go @@ -0,0 +1,74 @@ +// Copyright 2018 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package gtype_test + +import ( + "encoding/json" + "github.com/gogf/gf/container/gtype" + "github.com/gogf/gf/test/gtest" + "github.com/gogf/gf/util/gconv" + "math" + "sync" + "testing" +) + +func Test_Uint32(t *testing.T) { + gtest.Case(t, func() { + var wg sync.WaitGroup + addTimes := 1000 + i := gtype.NewUint32(0) + iClone := i.Clone() + gtest.AssertEQ(iClone.Set(1), uint32(0)) + gtest.AssertEQ(iClone.Val(), uint32(1)) + for index := 0; index < addTimes; index++ { + wg.Add(1) + go func() { + defer wg.Done() + i.Add(1) + }() + } + wg.Wait() + gtest.AssertEQ(uint32(addTimes), i.Val()) + + //空参测试 + i1 := gtype.NewUint32() + gtest.AssertEQ(i1.Val(), uint32(0)) + }) +} + +func Test_Uint32_JSON(t *testing.T) { + gtest.Case(t, func() { + i := gtype.NewUint32(math.MaxUint32) + b1, err1 := json.Marshal(i) + b2, err2 := json.Marshal(i.Val()) + gtest.Assert(err1, nil) + gtest.Assert(err2, nil) + gtest.Assert(b1, b2) + + i2 := gtype.NewUint32() + err := json.Unmarshal(b2, &i2) + gtest.Assert(err, nil) + gtest.Assert(i2.Val(), i) + }) +} + +func Test_Uint32_UnmarshalValue(t *testing.T) { + type T struct { + Name string + Var *gtype.Uint32 + } + gtest.Case(t, func() { + var t *T + err := gconv.Struct(map[string]interface{}{ + "name": "john", + "var": "123", + }, &t) + gtest.Assert(err, nil) + gtest.Assert(t.Name, "john") + gtest.Assert(t.Var.Val(), "123") + }) +} diff --git a/container/gtype/z_unit_uint64_test.go b/container/gtype/z_unit_uint64_test.go new file mode 100644 index 000000000..987871a5d --- /dev/null +++ b/container/gtype/z_unit_uint64_test.go @@ -0,0 +1,79 @@ +// Copyright 2018 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package gtype_test + +import ( + "encoding/json" + "github.com/gogf/gf/util/gconv" + "math" + "sync" + "testing" + + "github.com/gogf/gf/container/gtype" + "github.com/gogf/gf/test/gtest" +) + +type Temp struct { + Name string + Age int +} + +func Test_Uint64(t *testing.T) { + gtest.Case(t, func() { + var wg sync.WaitGroup + addTimes := 1000 + i := gtype.NewUint64(0) + iClone := i.Clone() + gtest.AssertEQ(iClone.Set(1), uint64(0)) + gtest.AssertEQ(iClone.Val(), uint64(1)) + for index := 0; index < addTimes; index++ { + wg.Add(1) + go func() { + defer wg.Done() + i.Add(1) + }() + } + wg.Wait() + gtest.AssertEQ(uint64(addTimes), i.Val()) + + //空参测试 + i1 := gtype.NewUint64() + gtest.AssertEQ(i1.Val(), uint64(0)) + }) +} +func Test_Uint64_JSON(t *testing.T) { + gtest.Case(t, func() { + i := gtype.NewUint64(math.MaxUint64) + b1, err1 := json.Marshal(i) + b2, err2 := json.Marshal(i.Val()) + gtest.Assert(err1, nil) + gtest.Assert(err2, nil) + gtest.Assert(b1, b2) + + i2 := gtype.NewUint64() + err := json.Unmarshal(b2, &i2) + gtest.Assert(err, nil) + gtest.Assert(i2.Val(), i) + }) +} + +func Test_Uint64_UnmarshalValue(t *testing.T) { + type T struct { + Name string + Var *gtype.Uint64 + } + gtest.Case(t, func() { + var t *T + err := gconv.Struct(map[string]interface{}{ + "name": "john", + "var": "123", + }, &t) + gtest.Assert(err, nil) + gtest.Assert(t.Name, "john") + gtest.Assert(t.Var.Val(), "123") + }) +} diff --git a/container/gtype/z_unit_uint_test.go b/container/gtype/z_unit_uint_test.go new file mode 100644 index 000000000..cffb4dae6 --- /dev/null +++ b/container/gtype/z_unit_uint_test.go @@ -0,0 +1,73 @@ +// Copyright 2018 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package gtype_test + +import ( + "encoding/json" + "github.com/gogf/gf/container/gtype" + "github.com/gogf/gf/test/gtest" + "github.com/gogf/gf/util/gconv" + "sync" + "testing" +) + +func Test_Uint(t *testing.T) { + gtest.Case(t, func() { + var wg sync.WaitGroup + addTimes := 1000 + i := gtype.NewUint(0) + iClone := i.Clone() + gtest.AssertEQ(iClone.Set(1), uint(0)) + gtest.AssertEQ(iClone.Val(), uint(1)) + for index := 0; index < addTimes; index++ { + wg.Add(1) + go func() { + defer wg.Done() + i.Add(1) + }() + } + wg.Wait() + gtest.AssertEQ(uint(addTimes), i.Val()) + + //空参测试 + i1 := gtype.NewUint() + gtest.AssertEQ(i1.Val(), uint(0)) + }) +} + +func Test_Uint_JSON(t *testing.T) { + gtest.Case(t, func() { + i := gtype.NewUint(666) + b1, err1 := json.Marshal(i) + b2, err2 := json.Marshal(i.Val()) + gtest.Assert(err1, nil) + gtest.Assert(err2, nil) + gtest.Assert(b1, b2) + + i2 := gtype.NewUint() + err := json.Unmarshal(b2, &i2) + gtest.Assert(err, nil) + gtest.Assert(i2.Val(), i) + }) +} + +func Test_Uint_UnmarshalValue(t *testing.T) { + type T struct { + Name string + Var *gtype.Uint + } + gtest.Case(t, func() { + var t *T + err := gconv.Struct(map[string]interface{}{ + "name": "john", + "var": "123", + }, &t) + gtest.Assert(err, nil) + gtest.Assert(t.Name, "john") + gtest.Assert(t.Var.Val(), "123") + }) +} diff --git a/container/gvar/gvar.go b/container/gvar/gvar.go index 7dc739c8b..1d4c87934 100644 --- a/container/gvar/gvar.go +++ b/container/gvar/gvar.go @@ -335,3 +335,9 @@ func (v *Var) UnmarshalJSON(b []byte) error { v.Set(i) return nil } + +// UnmarshalValue is an interface implement which sets any type of value for Var. +func (v *Var) UnmarshalValue(value interface{}) error { + v.Set(value) + return nil +} diff --git a/container/gvar/gvar_z_unit_test.go b/container/gvar/gvar_z_unit_test.go index 8ada16ce3..fcbd427ae 100644 --- a/container/gvar/gvar_z_unit_test.go +++ b/container/gvar/gvar_z_unit_test.go @@ -10,6 +10,7 @@ import ( "bytes" "encoding/binary" "encoding/json" + "github.com/gogf/gf/util/gconv" "math" "testing" "time" @@ -378,3 +379,20 @@ func Test_Json(t *testing.T) { gtest.Assert(v.String(), s) }) } + +func Test_UnmarshalValue(t *testing.T) { + type T struct { + Name string + Var *gvar.Var + } + gtest.Case(t, func() { + var t *T + err := gconv.Struct(map[string]interface{}{ + "name": "john", + "var": "v", + }, &t) + gtest.Assert(err, nil) + gtest.Assert(t.Name, "john") + gtest.Assert(t.Var.String(), "v") + }) +} diff --git a/encoding/gjson/gjson.go b/encoding/gjson/gjson.go index ae962bf41..25d1f45db 100644 --- a/encoding/gjson/gjson.go +++ b/encoding/gjson/gjson.go @@ -30,11 +30,6 @@ type Json struct { vc bool // Violence Check(false in default), which is used to access data when the hierarchical data key contains separator char. } -// MarshalJSON implements the interface MarshalJSON for json.Marshal. -func (j *Json) MarshalJSON() ([]byte, error) { - return j.ToJson() -} - // setValue sets to by . // Note: // 1. If value is nil and removed is true, means deleting this value; diff --git a/encoding/gjson/gjson_implements.go b/encoding/gjson/gjson_implements.go new file mode 100644 index 000000000..8a75e9ae7 --- /dev/null +++ b/encoding/gjson/gjson_implements.go @@ -0,0 +1,31 @@ +// Copyright 2019 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package gjson + +// MarshalJSON implements the interface MarshalJSON for json.Marshal. +func (j *Json) MarshalJSON() ([]byte, error) { + return j.ToJson() +} + +// UnmarshalJSON implements the interface UnmarshalJSON for json.Unmarshal. +func (j *Json) UnmarshalJSON(b []byte) error { + r, err := LoadContent(b) + if r != nil { + // Value copy. + *j = *r + } + return err +} + +// UnmarshalValue is an interface implement which sets any type of value for Json. +func (j *Json) UnmarshalValue(value interface{}) error { + if r := New(value); r != nil { + // Value copy. + *j = *r + } + return nil +} diff --git a/encoding/gjson/gjson_z_unit_implements_test.go b/encoding/gjson/gjson_z_unit_implements_test.go new file mode 100644 index 000000000..87938d448 --- /dev/null +++ b/encoding/gjson/gjson_z_unit_implements_test.go @@ -0,0 +1,72 @@ +// Copyright 2017 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package gjson_test + +import ( + "encoding/json" + "github.com/gogf/gf/util/gconv" + "testing" + + "github.com/gogf/gf/encoding/gjson" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/test/gtest" +) + +func TestJson_UnmarshalJSON(t *testing.T) { + data := []byte(`{"n":123456789, "m":{"k":"v"}, "a":[1,2,3]}`) + gtest.Case(t, func() { + j := gjson.New(nil) + err := json.Unmarshal(data, j) + gtest.Assert(err, nil) + gtest.Assert(j.Get("n"), "123456789") + gtest.Assert(j.Get("m"), g.Map{"k": "v"}) + gtest.Assert(j.Get("m.k"), "v") + gtest.Assert(j.Get("a"), g.Slice{1, 2, 3}) + gtest.Assert(j.Get("a.1"), 2) + }) +} + +func TestJson_UnmarshalValue(t *testing.T) { + type T struct { + Name string + Json *gjson.Json + } + // JSON + gtest.Case(t, func() { + var t *T + err := gconv.Struct(g.Map{ + "name": "john", + "json": []byte(`{"n":123456789, "m":{"k":"v"}, "a":[1,2,3]}`), + }, &t) + gtest.Assert(err, nil) + gtest.Assert(t.Name, "john") + gtest.Assert(t.Json.Get("n"), "123456789") + gtest.Assert(t.Json.Get("m"), g.Map{"k": "v"}) + gtest.Assert(t.Json.Get("m.k"), "v") + gtest.Assert(t.Json.Get("a"), g.Slice{1, 2, 3}) + gtest.Assert(t.Json.Get("a.1"), 2) + }) + // Map + gtest.Case(t, func() { + var t *T + err := gconv.Struct(g.Map{ + "name": "john", + "json": g.Map{ + "n": 123456789, + "m": g.Map{"k": "v"}, + "a": g.Slice{1, 2, 3}, + }, + }, &t) + gtest.Assert(err, nil) + gtest.Assert(t.Name, "john") + gtest.Assert(t.Json.Get("n"), "123456789") + gtest.Assert(t.Json.Get("m"), g.Map{"k": "v"}) + gtest.Assert(t.Json.Get("m.k"), "v") + gtest.Assert(t.Json.Get("a"), g.Slice{1, 2, 3}) + gtest.Assert(t.Json.Get("a.1"), 2) + }) +} diff --git a/util/gconv/gconv_map.go b/util/gconv/gconv_map.go index ef172defd..33163b34e 100644 --- a/util/gconv/gconv_map.go +++ b/util/gconv/gconv_map.go @@ -7,6 +7,7 @@ package gconv import ( + "encoding/json" "errors" "reflect" "strings" @@ -47,61 +48,69 @@ func doMapConvert(value interface{}, recursive bool, tags ...string) map[string] } else { // Assert the common combination of types, and finally it uses reflection. m := make(map[string]interface{}) - switch value.(type) { + switch r := value.(type) { + case string: + if len(r) > 0 && r[0] == '{' && r[len(r)-1] == '}' { + json.Unmarshal([]byte(r), &m) + } + case []byte: + if len(r) > 0 && r[0] == '{' && r[len(r)-1] == '}' { + json.Unmarshal(r, &m) + } case map[interface{}]interface{}: - for k, v := range value.(map[interface{}]interface{}) { + for k, v := range r { m[String(k)] = v } case map[interface{}]string: - for k, v := range value.(map[interface{}]string) { + for k, v := range r { m[String(k)] = v } case map[interface{}]int: - for k, v := range value.(map[interface{}]int) { + for k, v := range r { m[String(k)] = v } case map[interface{}]uint: - for k, v := range value.(map[interface{}]uint) { + for k, v := range r { m[String(k)] = v } case map[interface{}]float32: - for k, v := range value.(map[interface{}]float32) { + for k, v := range r { m[String(k)] = v } case map[interface{}]float64: - for k, v := range value.(map[interface{}]float64) { + for k, v := range r { m[String(k)] = v } case map[string]bool: - for k, v := range value.(map[string]bool) { + for k, v := range r { m[k] = v } case map[string]int: - for k, v := range value.(map[string]int) { + for k, v := range r { m[k] = v } case map[string]uint: - for k, v := range value.(map[string]uint) { + for k, v := range r { m[k] = v } case map[string]float32: - for k, v := range value.(map[string]float32) { + for k, v := range r { m[k] = v } case map[string]float64: - for k, v := range value.(map[string]float64) { + for k, v := range r { m[k] = v } case map[int]interface{}: - for k, v := range value.(map[int]interface{}) { + for k, v := range r { m[String(k)] = v } case map[int]string: - for k, v := range value.(map[int]string) { + for k, v := range r { m[String(k)] = v } case map[uint]string: - for k, v := range value.(map[uint]string) { + for k, v := range r { m[String(k)] = v } // Not a common type, then use reflection. diff --git a/util/gconv/gconv_struct.go b/util/gconv/gconv_struct.go index db4039440..47ba66ece 100644 --- a/util/gconv/gconv_struct.go +++ b/util/gconv/gconv_struct.go @@ -17,6 +17,12 @@ import ( "github.com/gogf/gf/internal/utilstr" ) +// apiUnmarshalValue is the interface for custom defined types customizing value assignment. +// Note that only pointer can implement interface apiUnmarshalValue. +type apiUnmarshalValue interface { + UnmarshalValue(interface{}) error +} + var ( // replaceCharReg is the regular expression object for replacing chars // in map keys and attribute names. @@ -42,6 +48,7 @@ func Struct(params interface{}, pointer interface{}, mapping ...map[string]strin if pointer == nil { return errors.New("object pointer cannot be nil") } + // paramsMap is the map[string]interface{} type variable for params. paramsMap := Map(params) if paramsMap == nil { @@ -63,10 +70,19 @@ func Struct(params interface{}, pointer interface{}, mapping ...map[string]strin } // It automatically creates struct object if necessary. // For example, if is **User, then is *User, which is a pointer to User. - if elem.Type().Kind() == reflect.Ptr && (!elem.IsValid() || elem.IsNil()) { - e := reflect.New(elem.Type().Elem()).Elem() - elem.Set(e.Addr()) - elem = e + if elem.Type().Kind() == reflect.Ptr { + if !elem.IsValid() || elem.IsNil() { + e := reflect.New(elem.Type().Elem()).Elem() + elem.Set(e.Addr()) + elem = e + } else { + // Assign value with interface Set. + // Note that only pointer can implement interface Set. + if v, ok := elem.Interface().(apiUnmarshalValue); ok { + v.UnmarshalValue(params) + return nil + } + } } // It only performs one converting to the same attribute. // doneMap is used to check repeated converting, its key is the attribute name of the struct. @@ -192,20 +208,17 @@ func StructDeep(params interface{}, pointer interface{}, mapping ...map[string]s return nil } -// 将参数值绑定到对象指定名称的属性上 +// bindVarToStructAttr sets value to struct object attribute by name. func bindVarToStructAttr(elem reflect.Value, name string, value interface{}) (err error) { structFieldValue := elem.FieldByName(name) - // 键名与对象属性匹配检测,map中如果有struct不存在的属性,那么不做处理,直接return if !structFieldValue.IsValid() { return nil } - // CanSet的属性必须为公开属性(首字母大写) + // CanSet checks whether attribute is public accessible. if !structFieldValue.CanSet() { return nil } - // 必须将value转换为struct属性的数据类型,这里必须用到gconv包 defer func() { - // 如果转换失败,那么可能是类型不匹配造成(例如属性包含自定义类型),那么执行递归转换 if recover() != nil { err = bindVarToReflectValue(structFieldValue, value) } @@ -214,20 +227,17 @@ func bindVarToStructAttr(elem reflect.Value, name string, value interface{}) (er return nil } -// 将参数值绑定到对象指定索引位置的属性上 +// bindVarToStructByIndex sets value to struct object attribute by index. func bindVarToStructByIndex(elem reflect.Value, index int, value interface{}) (err error) { structFieldValue := elem.FieldByIndex([]int{index}) - // 键名与对象属性匹配检测 if !structFieldValue.IsValid() { return nil } - // CanSet的属性必须为公开属性(首字母大写) + // CanSet checks whether attribute is public accessible. if !structFieldValue.CanSet() { return nil } - // 必须将value转换为struct属性的数据类型,这里必须用到gconv包 defer func() { - // 如果转换失败,那么可能是类型不匹配造成(例如属性包含自定义类型),那么执行递归转换 if recover() != nil { err = bindVarToReflectValue(structFieldValue, value) } @@ -236,16 +246,14 @@ func bindVarToStructByIndex(elem reflect.Value, index int, value interface{}) (e return nil } -// 当默认的基本类型转换失败时,通过recover判断后执行反射类型转换(处理复杂类型) -func bindVarToReflectValue(structFieldValue reflect.Value, value interface{}) error { +// bindVarToReflectValue sets to reflect value object . +func bindVarToReflectValue(structFieldValue reflect.Value, value interface{}) (err error) { switch structFieldValue.Kind() { - // 属性为结构体 case reflect.Struct: if err := Struct(value, structFieldValue); err != nil { structFieldValue.Set(reflect.ValueOf(value)) } - // 属性为数组类型 case reflect.Slice, reflect.Array: a := reflect.Value{} v := reflect.ValueOf(value) @@ -288,13 +296,19 @@ func bindVarToReflectValue(structFieldValue reflect.Value, value interface{}) er } structFieldValue.Set(a) - // 属性为指针类型 case reflect.Ptr: - e := reflect.New(structFieldValue.Type().Elem()).Elem() - if err := Struct(value, e); err != nil { - e.Set(reflect.ValueOf(value)) + item := reflect.New(structFieldValue.Type().Elem()) + // Assign value with interface Set. + // Note that only pointer can implement interface Set. + if v, ok := item.Interface().(apiUnmarshalValue); ok { + v.UnmarshalValue(value) + structFieldValue.Set(item) + return nil + } + elem := item.Elem() + if err = bindVarToReflectValue(elem, value); err == nil { + structFieldValue.Set(elem.Addr()) } - structFieldValue.Set(e.Addr()) case reflect.Interface: if value == nil { @@ -304,11 +318,17 @@ func bindVarToReflectValue(structFieldValue reflect.Value, value interface{}) er } default: - return errors.New( - fmt.Sprintf(`cannot convert to type "%s"`, - structFieldValue.Type().String(), - ), - ) + defer func() { + if e := recover(); e != nil { + err = errors.New( + fmt.Sprintf(`cannot convert "%d" to type "%s"`, + value, + structFieldValue.Type().String(), + ), + ) + } + }() + structFieldValue.Set(reflect.ValueOf(value)) } return nil }