mirror of
https://github.com/gogf/gf.git
synced 2025-04-05 11:18:50 +08:00
add map/[]map converting support for gconv.Scan;improve gconv.MaptoMaps
This commit is contained in:
parent
042f903157
commit
482e093331
@ -71,13 +71,6 @@ func (v *Var) MapToMap(pointer interface{}, mapping ...map[string]string) (err e
|
||||
return gconv.MapToMap(v.Val(), pointer, mapping...)
|
||||
}
|
||||
|
||||
// MapToMapDeep converts any map type variable <params> to another map type variable
|
||||
// <pointer> recursively.
|
||||
// See gconv.MapToMapDeep.
|
||||
func (v *Var) MapToMapDeep(pointer interface{}, mapping ...map[string]string) (err error) {
|
||||
return gconv.MapToMapDeep(v.Val(), pointer, mapping...)
|
||||
}
|
||||
|
||||
// MapToMaps converts any map type variable <params> to another map type variable <pointer>.
|
||||
// See gconv.MapToMaps.
|
||||
func (v *Var) MapToMaps(pointer interface{}, mapping ...map[string]string) (err error) {
|
||||
|
@ -354,13 +354,6 @@ func (j *Json) GetMapToMap(pattern string, pointer interface{}, mapping ...map[s
|
||||
return gconv.MapToMap(j.Get(pattern), pointer, mapping...)
|
||||
}
|
||||
|
||||
// GetMapToMapDeep retrieves the value by specified <pattern> and converts it to specified map
|
||||
// variable recursively.
|
||||
// See gconv.MapToMapDeep.
|
||||
func (j *Json) GetMapToMapDeep(pattern string, pointer interface{}, mapping ...map[string]string) error {
|
||||
return gconv.MapToMapDeep(j.Get(pattern), pointer, mapping...)
|
||||
}
|
||||
|
||||
// GetMapToMaps retrieves the value by specified <pattern> and converts it to specified map slice
|
||||
// variable.
|
||||
// See gconv.MapToMaps.
|
||||
|
@ -85,15 +85,6 @@ func (j *Json) ToMapToMap(pointer interface{}, mapping ...map[string]string) err
|
||||
return gconv.MapToMap(*(j.p), pointer, mapping...)
|
||||
}
|
||||
|
||||
// ToMapToMapDeep converts current Json object to specified map variable recursively.
|
||||
// The parameter of <pointer> should be type of *map.
|
||||
// Deprecated, use MapToMap instead.
|
||||
func (j *Json) ToMapToMapDeep(pointer interface{}, mapping ...map[string]string) error {
|
||||
j.mu.RLock()
|
||||
defer j.mu.RUnlock()
|
||||
return gconv.MapToMapDeep(*(j.p), pointer, mapping...)
|
||||
}
|
||||
|
||||
// ToMapToMaps converts current Json object to specified map variable slice.
|
||||
// The parameter of <pointer> should be type of []map/*map.
|
||||
// Deprecated, use MapToMaps instead.
|
||||
|
@ -333,16 +333,6 @@ func (c *Config) GetMapToMap(pattern string, pointer interface{}, mapping ...map
|
||||
return errors.New("configuration not found")
|
||||
}
|
||||
|
||||
// GetMapToMapDeep retrieves the value by specified `pattern` and converts it to specified map
|
||||
// variable recursively.
|
||||
// See gconv.MapToMapDeep.
|
||||
func (c *Config) GetMapToMapDeep(pattern string, pointer interface{}, mapping ...map[string]string) error {
|
||||
if j := c.getJson(); j != nil {
|
||||
return j.GetMapToMapDeep(pattern, pointer, mapping...)
|
||||
}
|
||||
return errors.New("configuration not found")
|
||||
}
|
||||
|
||||
// GetMapToMaps retrieves the value by specified `pattern` and converts it to specified map slice
|
||||
// variable.
|
||||
// See gconv.MapToMaps.
|
||||
@ -426,15 +416,6 @@ func (c *Config) ToMapToMap(pointer interface{}, mapping ...map[string]string) e
|
||||
return errors.New("configuration not found")
|
||||
}
|
||||
|
||||
// ToMapToMapDeep converts current Json object to specified map variable recursively.
|
||||
// The parameter of `pointer` should be type of *map.
|
||||
func (c *Config) ToMapToMapDeep(pointer interface{}, mapping ...map[string]string) error {
|
||||
if j := c.getJson(); j != nil {
|
||||
return j.ToMapToMapDeep(pointer, mapping...)
|
||||
}
|
||||
return errors.New("configuration not found")
|
||||
}
|
||||
|
||||
// ToMapToMaps converts current Json object to specified map variable slice.
|
||||
// The parameter of `pointer` should be type of []map/*map.
|
||||
func (c *Config) ToMapToMaps(pointer interface{}, mapping ...map[string]string) error {
|
||||
|
@ -45,8 +45,8 @@ var (
|
||||
StructTagPriority = []string{"gconv", "param", "params", "c", "p", "json"}
|
||||
)
|
||||
|
||||
// Convert converts the variable <i> to the type <t>, the type <t> is specified by string.
|
||||
// The optional parameter <params> is used for additional necessary parameter for this conversion.
|
||||
// Convert converts the variable `i` to the type `t`, the type `t` is specified by string.
|
||||
// The optional parameter `params` is used for additional necessary parameter for this conversion.
|
||||
// It supports common types conversion as its conversion based on type name string.
|
||||
func Convert(any interface{}, t string, params ...interface{}) interface{} {
|
||||
switch t {
|
||||
@ -277,7 +277,7 @@ func Convert(any interface{}, t string, params ...interface{}) interface{} {
|
||||
}
|
||||
}
|
||||
|
||||
// Byte converts <i> to byte.
|
||||
// Byte converts `i` to byte.
|
||||
func Byte(any interface{}) byte {
|
||||
if v, ok := any.(byte); ok {
|
||||
return v
|
||||
@ -285,7 +285,7 @@ func Byte(any interface{}) byte {
|
||||
return Uint8(any)
|
||||
}
|
||||
|
||||
// Bytes converts <i> to []byte.
|
||||
// Bytes converts `i` to []byte.
|
||||
func Bytes(any interface{}) []byte {
|
||||
if any == nil {
|
||||
return nil
|
||||
@ -303,7 +303,7 @@ func Bytes(any interface{}) []byte {
|
||||
}
|
||||
}
|
||||
|
||||
// Rune converts <i> to rune.
|
||||
// Rune converts `i` to rune.
|
||||
func Rune(any interface{}) rune {
|
||||
if v, ok := any.(rune); ok {
|
||||
return v
|
||||
@ -311,7 +311,7 @@ func Rune(any interface{}) rune {
|
||||
return rune(Int32(any))
|
||||
}
|
||||
|
||||
// Runes converts <i> to []rune.
|
||||
// Runes converts `i` to []rune.
|
||||
func Runes(any interface{}) []rune {
|
||||
if v, ok := any.([]rune); ok {
|
||||
return v
|
||||
@ -319,7 +319,7 @@ func Runes(any interface{}) []rune {
|
||||
return []rune(String(any))
|
||||
}
|
||||
|
||||
// String converts <i> to string.
|
||||
// String converts `i` to string.
|
||||
// It's most common used converting function.
|
||||
func String(any interface{}) string {
|
||||
if any == nil {
|
||||
@ -422,8 +422,8 @@ func String(any interface{}) string {
|
||||
}
|
||||
}
|
||||
|
||||
// Bool converts <i> to bool.
|
||||
// It returns false if <i> is: false, "", 0, "false", "off", "no", empty slice/map.
|
||||
// Bool converts `i` to bool.
|
||||
// It returns false if `i` is: false, "", 0, "false", "off", "no", empty slice/map.
|
||||
func Bool(any interface{}) bool {
|
||||
if any == nil {
|
||||
return false
|
||||
@ -467,7 +467,7 @@ func Bool(any interface{}) bool {
|
||||
}
|
||||
}
|
||||
|
||||
// Int converts <i> to int.
|
||||
// Int converts `i` to int.
|
||||
func Int(any interface{}) int {
|
||||
if any == nil {
|
||||
return 0
|
||||
@ -478,7 +478,7 @@ func Int(any interface{}) int {
|
||||
return int(Int64(any))
|
||||
}
|
||||
|
||||
// Int8 converts <i> to int8.
|
||||
// Int8 converts `i` to int8.
|
||||
func Int8(any interface{}) int8 {
|
||||
if any == nil {
|
||||
return 0
|
||||
@ -489,7 +489,7 @@ func Int8(any interface{}) int8 {
|
||||
return int8(Int64(any))
|
||||
}
|
||||
|
||||
// Int16 converts <i> to int16.
|
||||
// Int16 converts `i` to int16.
|
||||
func Int16(any interface{}) int16 {
|
||||
if any == nil {
|
||||
return 0
|
||||
@ -500,7 +500,7 @@ func Int16(any interface{}) int16 {
|
||||
return int16(Int64(any))
|
||||
}
|
||||
|
||||
// Int32 converts <i> to int32.
|
||||
// Int32 converts `i` to int32.
|
||||
func Int32(any interface{}) int32 {
|
||||
if any == nil {
|
||||
return 0
|
||||
@ -511,7 +511,7 @@ func Int32(any interface{}) int32 {
|
||||
return int32(Int64(any))
|
||||
}
|
||||
|
||||
// Int64 converts <i> to int64.
|
||||
// Int64 converts `i` to int64.
|
||||
func Int64(any interface{}) int64 {
|
||||
if any == nil {
|
||||
return 0
|
||||
@ -592,7 +592,7 @@ func Int64(any interface{}) int64 {
|
||||
}
|
||||
}
|
||||
|
||||
// Uint converts <i> to uint.
|
||||
// Uint converts `i` to uint.
|
||||
func Uint(any interface{}) uint {
|
||||
if any == nil {
|
||||
return 0
|
||||
@ -603,7 +603,7 @@ func Uint(any interface{}) uint {
|
||||
return uint(Uint64(any))
|
||||
}
|
||||
|
||||
// Uint8 converts <i> to uint8.
|
||||
// Uint8 converts `i` to uint8.
|
||||
func Uint8(any interface{}) uint8 {
|
||||
if any == nil {
|
||||
return 0
|
||||
@ -614,7 +614,7 @@ func Uint8(any interface{}) uint8 {
|
||||
return uint8(Uint64(any))
|
||||
}
|
||||
|
||||
// Uint16 converts <i> to uint16.
|
||||
// Uint16 converts `i` to uint16.
|
||||
func Uint16(any interface{}) uint16 {
|
||||
if any == nil {
|
||||
return 0
|
||||
@ -625,7 +625,7 @@ func Uint16(any interface{}) uint16 {
|
||||
return uint16(Uint64(any))
|
||||
}
|
||||
|
||||
// Uint32 converts <i> to uint32.
|
||||
// Uint32 converts `i` to uint32.
|
||||
func Uint32(any interface{}) uint32 {
|
||||
if any == nil {
|
||||
return 0
|
||||
@ -636,7 +636,7 @@ func Uint32(any interface{}) uint32 {
|
||||
return uint32(Uint64(any))
|
||||
}
|
||||
|
||||
// Uint64 converts <i> to uint64.
|
||||
// Uint64 converts `i` to uint64.
|
||||
func Uint64(any interface{}) uint64 {
|
||||
if any == nil {
|
||||
return 0
|
||||
@ -699,7 +699,7 @@ func Uint64(any interface{}) uint64 {
|
||||
}
|
||||
}
|
||||
|
||||
// Float32 converts <i> to float32.
|
||||
// Float32 converts `i` to float32.
|
||||
func Float32(any interface{}) float32 {
|
||||
if any == nil {
|
||||
return 0
|
||||
@ -720,7 +720,7 @@ func Float32(any interface{}) float32 {
|
||||
}
|
||||
}
|
||||
|
||||
// Float64 converts <i> to float64.
|
||||
// Float64 converts `i` to float64.
|
||||
func Float64(any interface{}) float64 {
|
||||
if any == nil {
|
||||
return 0
|
||||
|
@ -7,7 +7,6 @@
|
||||
package gconv
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/errors/gerror"
|
||||
"github.com/gogf/gf/internal/json"
|
||||
"reflect"
|
||||
"strings"
|
||||
@ -16,17 +15,17 @@ import (
|
||||
"github.com/gogf/gf/internal/utils"
|
||||
)
|
||||
|
||||
// Map converts any variable <value> to map[string]interface{}. If the parameter <value> is not a
|
||||
// Map converts any variable `value` to map[string]interface{}. If the parameter `value` is not a
|
||||
// map/struct/*struct type, then the conversion will fail and returns nil.
|
||||
//
|
||||
// If <value> is a struct/*struct object, the second parameter <tags> specifies the most priority
|
||||
// If `value` is a struct/*struct object, the second parameter `tags` specifies the most priority
|
||||
// tags that will be detected, otherwise it detects the tags in order of:
|
||||
// gconv, json, field name.
|
||||
func Map(value interface{}, tags ...string) map[string]interface{} {
|
||||
return doMapConvert(value, false, tags...)
|
||||
}
|
||||
|
||||
// MapDeep does Map function recursively, which means if the attribute of <value>
|
||||
// MapDeep does Map function recursively, which means if the attribute of `value`
|
||||
// is also a struct/*struct, calls Map function on this attribute converting it to
|
||||
// a map[string]interface{} type variable.
|
||||
// Also see Map.
|
||||
@ -35,7 +34,7 @@ func MapDeep(value interface{}, tags ...string) map[string]interface{} {
|
||||
}
|
||||
|
||||
// doMapConvert implements the map converting.
|
||||
// It automatically checks and converts json string to map if <value> is string/[]byte.
|
||||
// It automatically checks and converts json string to map if `value` is string/[]byte.
|
||||
//
|
||||
// TODO completely implement the recursive converting for all types, especially the map.
|
||||
func doMapConvert(value interface{}, recursive bool, tags ...string) map[string]interface{} {
|
||||
@ -154,7 +153,7 @@ func doMapConvert(value interface{}, recursive bool, tags ...string) map[string]
|
||||
reflectKind = reflectValue.Kind()
|
||||
}
|
||||
switch reflectKind {
|
||||
// If <value> is type of array, it converts the value of even number index as its key and
|
||||
// If `value` is type of array, it converts the value of even number index as its key and
|
||||
// the value of odd number index as its corresponding value, for example:
|
||||
// []string{"k1","v1","k2","v2"} => map[string]interface{}{"k1":"v1", "k2":"v2"}
|
||||
// []string{"k1","v1","k2"} => map[string]interface{}{"k1":"v1", "k2":nil}
|
||||
@ -354,7 +353,7 @@ func doMapConvertForMapOrStructValue(isRoot bool, value interface{}, recursive b
|
||||
return value
|
||||
}
|
||||
|
||||
// MapStrStr converts <value> to map[string]string.
|
||||
// MapStrStr converts `value` to map[string]string.
|
||||
// Note that there might be data copy for this map type converting.
|
||||
func MapStrStr(value interface{}, tags ...string) map[string]string {
|
||||
if r, ok := value.(map[string]string); ok {
|
||||
@ -371,7 +370,7 @@ func MapStrStr(value interface{}, tags ...string) map[string]string {
|
||||
return nil
|
||||
}
|
||||
|
||||
// MapStrStrDeep converts <value> to map[string]string recursively.
|
||||
// MapStrStrDeep converts `value` to map[string]string recursively.
|
||||
// Note that there might be data copy for this map type converting.
|
||||
func MapStrStrDeep(value interface{}, tags ...string) map[string]string {
|
||||
if r, ok := value.(map[string]string); ok {
|
||||
@ -387,196 +386,3 @@ func MapStrStrDeep(value interface{}, tags ...string) map[string]string {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// MapToMap converts any map type variable <params> to another map type variable <pointer>
|
||||
// using reflect.
|
||||
// See doMapToMap.
|
||||
func MapToMap(params interface{}, pointer interface{}, mapping ...map[string]string) error {
|
||||
return doMapToMap(params, pointer, mapping...)
|
||||
}
|
||||
|
||||
// MapToMapDeep converts any map type variable <params> to another map type variable <pointer>
|
||||
// using reflect recursively.
|
||||
// Deprecated, use MapToMap instead.
|
||||
func MapToMapDeep(params interface{}, pointer interface{}, mapping ...map[string]string) error {
|
||||
return doMapToMap(params, pointer, mapping...)
|
||||
}
|
||||
|
||||
// doMapToMap converts any map type variable <params> to another map type variable <pointer>.
|
||||
//
|
||||
// The parameter <params> can be any type of map, like:
|
||||
// map[string]string, map[string]struct, , map[string]*struct, etc.
|
||||
//
|
||||
// The parameter <pointer> should be type of *map, like:
|
||||
// map[int]string, map[string]struct, , map[string]*struct, etc.
|
||||
//
|
||||
// The optional parameter <mapping> is used for struct attribute to map key mapping, which makes
|
||||
// sense only if the items of original map <params> is type struct.
|
||||
func doMapToMap(params interface{}, pointer interface{}, mapping ...map[string]string) (err error) {
|
||||
var (
|
||||
paramsRv = reflect.ValueOf(params)
|
||||
paramsKind = paramsRv.Kind()
|
||||
)
|
||||
if paramsKind == reflect.Ptr {
|
||||
paramsRv = paramsRv.Elem()
|
||||
paramsKind = paramsRv.Kind()
|
||||
}
|
||||
if paramsKind != reflect.Map {
|
||||
return gerror.New("params should be type of map")
|
||||
}
|
||||
// Empty params map, no need continue.
|
||||
if paramsRv.Len() == 0 {
|
||||
return nil
|
||||
}
|
||||
var pointerRv reflect.Value
|
||||
if v, ok := pointer.(reflect.Value); ok {
|
||||
pointerRv = v
|
||||
} else {
|
||||
pointerRv = reflect.ValueOf(pointer)
|
||||
}
|
||||
pointerKind := pointerRv.Kind()
|
||||
for pointerKind == reflect.Ptr {
|
||||
pointerRv = pointerRv.Elem()
|
||||
pointerKind = pointerRv.Kind()
|
||||
}
|
||||
if pointerKind != reflect.Map {
|
||||
return gerror.New("pointer should be type of *map")
|
||||
}
|
||||
defer func() {
|
||||
// Catch the panic, especially the reflect operation panics.
|
||||
if exception := recover(); exception != nil {
|
||||
if e, ok := exception.(errorStack); ok {
|
||||
err = e
|
||||
} else {
|
||||
err = gerror.NewSkipf(1, "%v", exception)
|
||||
}
|
||||
}
|
||||
}()
|
||||
var (
|
||||
paramsKeys = paramsRv.MapKeys()
|
||||
pointerKeyType = pointerRv.Type().Key()
|
||||
pointerValueType = pointerRv.Type().Elem()
|
||||
pointerValueKind = pointerValueType.Kind()
|
||||
dataMap = reflect.MakeMapWithSize(pointerRv.Type(), len(paramsKeys))
|
||||
)
|
||||
// Retrieve the true element type of target map.
|
||||
if pointerValueKind == reflect.Ptr {
|
||||
pointerValueKind = pointerValueType.Elem().Kind()
|
||||
}
|
||||
for _, key := range paramsKeys {
|
||||
e := reflect.New(pointerValueType).Elem()
|
||||
switch pointerValueKind {
|
||||
case reflect.Map, reflect.Struct:
|
||||
if err = Struct(paramsRv.MapIndex(key).Interface(), e, mapping...); err != nil {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
e.Set(
|
||||
reflect.ValueOf(
|
||||
Convert(
|
||||
paramsRv.MapIndex(key).Interface(),
|
||||
pointerValueType.String(),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
dataMap.SetMapIndex(
|
||||
reflect.ValueOf(
|
||||
Convert(
|
||||
key.Interface(),
|
||||
pointerKeyType.Name(),
|
||||
),
|
||||
),
|
||||
e,
|
||||
)
|
||||
}
|
||||
pointerRv.Set(dataMap)
|
||||
return nil
|
||||
}
|
||||
|
||||
// MapToMaps converts any map type variable <params> to another map type variable <pointer>.
|
||||
// See doMapToMaps.
|
||||
func MapToMaps(params interface{}, pointer interface{}, mapping ...map[string]string) error {
|
||||
return doMapToMaps(params, pointer, mapping...)
|
||||
}
|
||||
|
||||
// MapToMapsDeep converts any map type variable <params> to another map type variable
|
||||
// <pointer> recursively.
|
||||
// Deprecated, use MapToMaps instead.
|
||||
func MapToMapsDeep(params interface{}, pointer interface{}, mapping ...map[string]string) error {
|
||||
return doMapToMaps(params, pointer, mapping...)
|
||||
}
|
||||
|
||||
// doMapToMaps converts any map type variable <params> to another map type variable <pointer>.
|
||||
//
|
||||
// The parameter <params> can be any type of map, of which the item type is slice map, like:
|
||||
// map[int][]map, map[string][]map.
|
||||
//
|
||||
// The parameter <pointer> should be type of *map, of which the item type is slice map, like:
|
||||
// map[string][]struct, map[string][]*struct.
|
||||
//
|
||||
// The optional parameter <mapping> is used for struct attribute to map key mapping, which makes
|
||||
// sense only if the items of original map is type struct.
|
||||
//
|
||||
// TODO it's supposed supporting target type <pointer> like: map[int][]map, map[string][]map.
|
||||
func doMapToMaps(params interface{}, pointer interface{}, mapping ...map[string]string) (err error) {
|
||||
var (
|
||||
paramsRv = reflect.ValueOf(params)
|
||||
paramsKind = paramsRv.Kind()
|
||||
)
|
||||
if paramsKind == reflect.Ptr {
|
||||
paramsRv = paramsRv.Elem()
|
||||
paramsKind = paramsRv.Kind()
|
||||
}
|
||||
if paramsKind != reflect.Map {
|
||||
return gerror.New("params should be type of map")
|
||||
}
|
||||
// Empty params map, no need continue.
|
||||
if paramsRv.Len() == 0 {
|
||||
return nil
|
||||
}
|
||||
var (
|
||||
pointerRv = reflect.ValueOf(pointer)
|
||||
pointerKind = pointerRv.Kind()
|
||||
)
|
||||
for pointerKind == reflect.Ptr {
|
||||
pointerRv = pointerRv.Elem()
|
||||
pointerKind = pointerRv.Kind()
|
||||
}
|
||||
if pointerKind != reflect.Map {
|
||||
return gerror.New("pointer should be type of *map/**map")
|
||||
}
|
||||
defer func() {
|
||||
// Catch the panic, especially the reflect operation panics.
|
||||
if exception := recover(); exception != nil {
|
||||
if e, ok := exception.(errorStack); ok {
|
||||
err = e
|
||||
} else {
|
||||
err = gerror.NewSkipf(1, "%v", exception)
|
||||
}
|
||||
}
|
||||
}()
|
||||
var (
|
||||
paramsKeys = paramsRv.MapKeys()
|
||||
pointerKeyType = pointerRv.Type().Key()
|
||||
pointerValueType = pointerRv.Type().Elem()
|
||||
dataMap = reflect.MakeMapWithSize(pointerRv.Type(), len(paramsKeys))
|
||||
)
|
||||
for _, key := range paramsKeys {
|
||||
e := reflect.New(pointerValueType).Elem()
|
||||
if err = Structs(paramsRv.MapIndex(key).Interface(), e.Addr(), mapping...); err != nil {
|
||||
return err
|
||||
}
|
||||
dataMap.SetMapIndex(
|
||||
reflect.ValueOf(
|
||||
Convert(
|
||||
key.Interface(),
|
||||
pointerKeyType.Name(),
|
||||
),
|
||||
),
|
||||
e,
|
||||
)
|
||||
}
|
||||
pointerRv.Set(dataMap)
|
||||
return nil
|
||||
}
|
||||
|
119
util/gconv/gconv_maps.go
Normal file
119
util/gconv/gconv_maps.go
Normal file
@ -0,0 +1,119 @@
|
||||
// Copyright GoFrame Author(https://goframe.org). 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 gconv
|
||||
|
||||
import "github.com/gogf/gf/internal/json"
|
||||
|
||||
// SliceMap is alias of Maps.
|
||||
func SliceMap(any interface{}) []map[string]interface{} {
|
||||
return Maps(any)
|
||||
}
|
||||
|
||||
// SliceMapDeep is alias of MapsDeep.
|
||||
func SliceMapDeep(any interface{}) []map[string]interface{} {
|
||||
return MapsDeep(any)
|
||||
}
|
||||
|
||||
// SliceStruct is alias of Structs.
|
||||
func SliceStruct(params interface{}, pointer interface{}, mapping ...map[string]string) (err error) {
|
||||
return Structs(params, pointer, mapping...)
|
||||
}
|
||||
|
||||
// Maps converts `i` to []map[string]interface{}.
|
||||
// Note that it automatically checks and converts json string to []map if `value` is string/[]byte.
|
||||
func Maps(value interface{}, tags ...string) []map[string]interface{} {
|
||||
if value == nil {
|
||||
return nil
|
||||
}
|
||||
switch r := value.(type) {
|
||||
case string:
|
||||
list := make([]map[string]interface{}, 0)
|
||||
if len(r) > 0 && r[0] == '[' && r[len(r)-1] == ']' {
|
||||
if err := json.Unmarshal([]byte(r), &list); err != nil {
|
||||
return nil
|
||||
}
|
||||
return list
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
|
||||
case []byte:
|
||||
list := make([]map[string]interface{}, 0)
|
||||
if len(r) > 0 && r[0] == '[' && r[len(r)-1] == ']' {
|
||||
if err := json.Unmarshal(r, &list); err != nil {
|
||||
return nil
|
||||
}
|
||||
return list
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
|
||||
case []map[string]interface{}:
|
||||
return r
|
||||
|
||||
default:
|
||||
array := Interfaces(value)
|
||||
if len(array) == 0 {
|
||||
return nil
|
||||
}
|
||||
list := make([]map[string]interface{}, len(array))
|
||||
for k, v := range array {
|
||||
list[k] = Map(v, tags...)
|
||||
}
|
||||
return list
|
||||
}
|
||||
}
|
||||
|
||||
// MapsDeep converts `i` to []map[string]interface{} recursively.
|
||||
//
|
||||
// TODO completely implement the recursive converting for all types.
|
||||
func MapsDeep(value interface{}, tags ...string) []map[string]interface{} {
|
||||
if value == nil {
|
||||
return nil
|
||||
}
|
||||
switch r := value.(type) {
|
||||
case string:
|
||||
list := make([]map[string]interface{}, 0)
|
||||
if len(r) > 0 && r[0] == '[' && r[len(r)-1] == ']' {
|
||||
if err := json.Unmarshal([]byte(r), &list); err != nil {
|
||||
return nil
|
||||
}
|
||||
return list
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
|
||||
case []byte:
|
||||
list := make([]map[string]interface{}, 0)
|
||||
if len(r) > 0 && r[0] == '[' && r[len(r)-1] == ']' {
|
||||
if err := json.Unmarshal(r, &list); err != nil {
|
||||
return nil
|
||||
}
|
||||
return list
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
|
||||
case []map[string]interface{}:
|
||||
list := make([]map[string]interface{}, len(r))
|
||||
for k, v := range r {
|
||||
list[k] = MapDeep(v, tags...)
|
||||
}
|
||||
return list
|
||||
|
||||
default:
|
||||
array := Interfaces(value)
|
||||
if len(array) == 0 {
|
||||
return nil
|
||||
}
|
||||
list := make([]map[string]interface{}, len(array))
|
||||
for k, v := range array {
|
||||
list[k] = MapDeep(v, tags...)
|
||||
}
|
||||
return list
|
||||
}
|
||||
}
|
141
util/gconv/gconv_maptomap.go
Normal file
141
util/gconv/gconv_maptomap.go
Normal file
@ -0,0 +1,141 @@
|
||||
// Copyright GoFrame Author(https://goframe.org). 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 gconv
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/errors/gerror"
|
||||
"github.com/gogf/gf/internal/json"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// MapToMap converts any map type variable `params` to another map type variable `pointer`
|
||||
// using reflect.
|
||||
// See doMapToMap.
|
||||
func MapToMap(params interface{}, pointer interface{}, mapping ...map[string]string) error {
|
||||
return doMapToMap(params, pointer, mapping...)
|
||||
}
|
||||
|
||||
// doMapToMap converts any map type variable `params` to another map type variable `pointer`.
|
||||
//
|
||||
// The parameter `params` can be any type of map, like:
|
||||
// map[string]string, map[string]struct, , map[string]*struct, etc.
|
||||
//
|
||||
// The parameter `pointer` should be type of *map, like:
|
||||
// map[int]string, map[string]struct, , map[string]*struct, etc.
|
||||
//
|
||||
// The optional parameter `mapping` is used for struct attribute to map key mapping, which makes
|
||||
// sense only if the items of original map `params` is type struct.
|
||||
func doMapToMap(params interface{}, pointer interface{}, mapping ...map[string]string) (err error) {
|
||||
// If given `params` is JSON, it then uses json.Unmarshal doing the converting.
|
||||
switch r := params.(type) {
|
||||
case []byte:
|
||||
if json.Valid(r) {
|
||||
if rv, ok := pointer.(reflect.Value); ok {
|
||||
if rv.Kind() == reflect.Ptr {
|
||||
return json.Unmarshal(r, rv.Interface())
|
||||
}
|
||||
} else {
|
||||
return json.Unmarshal(r, pointer)
|
||||
}
|
||||
}
|
||||
case string:
|
||||
if paramsBytes := []byte(r); json.Valid(paramsBytes) {
|
||||
if rv, ok := pointer.(reflect.Value); ok {
|
||||
if rv.Kind() == reflect.Ptr {
|
||||
return json.Unmarshal(paramsBytes, rv.Interface())
|
||||
}
|
||||
} else {
|
||||
return json.Unmarshal(paramsBytes, pointer)
|
||||
}
|
||||
}
|
||||
}
|
||||
var (
|
||||
paramsRv reflect.Value
|
||||
paramsKind reflect.Kind
|
||||
)
|
||||
if v, ok := params.(reflect.Value); ok {
|
||||
paramsRv = v
|
||||
} else {
|
||||
paramsRv = reflect.ValueOf(params)
|
||||
}
|
||||
paramsKind = paramsRv.Kind()
|
||||
if paramsKind == reflect.Ptr {
|
||||
paramsRv = paramsRv.Elem()
|
||||
paramsKind = paramsRv.Kind()
|
||||
}
|
||||
if paramsKind != reflect.Map {
|
||||
return doMapToMap(Map(params), pointer, mapping...)
|
||||
}
|
||||
// Empty params map, no need continue.
|
||||
if paramsRv.Len() == 0 {
|
||||
return nil
|
||||
}
|
||||
var pointerRv reflect.Value
|
||||
if v, ok := pointer.(reflect.Value); ok {
|
||||
pointerRv = v
|
||||
} else {
|
||||
pointerRv = reflect.ValueOf(pointer)
|
||||
}
|
||||
pointerKind := pointerRv.Kind()
|
||||
for pointerKind == reflect.Ptr {
|
||||
pointerRv = pointerRv.Elem()
|
||||
pointerKind = pointerRv.Kind()
|
||||
}
|
||||
if pointerKind != reflect.Map {
|
||||
return gerror.Newf("pointer should be type of *map, but got:%s", pointerKind)
|
||||
}
|
||||
defer func() {
|
||||
// Catch the panic, especially the reflect operation panics.
|
||||
if exception := recover(); exception != nil {
|
||||
if e, ok := exception.(errorStack); ok {
|
||||
err = e
|
||||
} else {
|
||||
err = gerror.NewSkipf(1, "%v", exception)
|
||||
}
|
||||
}
|
||||
}()
|
||||
var (
|
||||
paramsKeys = paramsRv.MapKeys()
|
||||
pointerKeyType = pointerRv.Type().Key()
|
||||
pointerValueType = pointerRv.Type().Elem()
|
||||
pointerValueKind = pointerValueType.Kind()
|
||||
dataMap = reflect.MakeMapWithSize(pointerRv.Type(), len(paramsKeys))
|
||||
)
|
||||
// Retrieve the true element type of target map.
|
||||
if pointerValueKind == reflect.Ptr {
|
||||
pointerValueKind = pointerValueType.Elem().Kind()
|
||||
}
|
||||
for _, key := range paramsKeys {
|
||||
e := reflect.New(pointerValueType).Elem()
|
||||
switch pointerValueKind {
|
||||
case reflect.Map, reflect.Struct:
|
||||
if err = Struct(paramsRv.MapIndex(key).Interface(), e, mapping...); err != nil {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
e.Set(
|
||||
reflect.ValueOf(
|
||||
Convert(
|
||||
paramsRv.MapIndex(key).Interface(),
|
||||
pointerValueType.String(),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
dataMap.SetMapIndex(
|
||||
reflect.ValueOf(
|
||||
Convert(
|
||||
key.Interface(),
|
||||
pointerKeyType.Name(),
|
||||
),
|
||||
),
|
||||
e,
|
||||
)
|
||||
}
|
||||
pointerRv.Set(dataMap)
|
||||
return nil
|
||||
}
|
146
util/gconv/gconv_maptomaps.go
Normal file
146
util/gconv/gconv_maptomaps.go
Normal file
@ -0,0 +1,146 @@
|
||||
// Copyright GoFrame Author(https://goframe.org). 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 gconv
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/errors/gerror"
|
||||
"github.com/gogf/gf/internal/json"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// MapToMaps converts any slice type variable `params` to another map slice type variable `pointer`.
|
||||
// See doMapToMaps.
|
||||
func MapToMaps(params interface{}, pointer interface{}, mapping ...map[string]string) error {
|
||||
return doMapToMaps(params, pointer, mapping...)
|
||||
}
|
||||
|
||||
// MapToMapsDeep converts any slice type variable `params` to another map slice type variable
|
||||
// `pointer` recursively.
|
||||
// Deprecated, use MapToMaps instead.
|
||||
func MapToMapsDeep(params interface{}, pointer interface{}, mapping ...map[string]string) error {
|
||||
return doMapToMaps(params, pointer, mapping...)
|
||||
}
|
||||
|
||||
// doMapToMaps converts any map type variable `params` to another map slice variable `pointer`.
|
||||
//
|
||||
// The parameter `params` can be type of []map, []*map, []struct, []*struct.
|
||||
//
|
||||
// The parameter `pointer` should be type of []map, []*map.
|
||||
//
|
||||
// The optional parameter `mapping` is used for struct attribute to map key mapping, which makes
|
||||
// sense only if the item of `params` is type struct.
|
||||
func doMapToMaps(params interface{}, pointer interface{}, mapping ...map[string]string) (err error) {
|
||||
// If given `params` is JSON, it then uses json.Unmarshal doing the converting.
|
||||
switch r := params.(type) {
|
||||
case []byte:
|
||||
if json.Valid(r) {
|
||||
if rv, ok := pointer.(reflect.Value); ok {
|
||||
if rv.Kind() == reflect.Ptr {
|
||||
return json.Unmarshal(r, rv.Interface())
|
||||
}
|
||||
} else {
|
||||
return json.Unmarshal(r, pointer)
|
||||
}
|
||||
}
|
||||
case string:
|
||||
if paramsBytes := []byte(r); json.Valid(paramsBytes) {
|
||||
if rv, ok := pointer.(reflect.Value); ok {
|
||||
if rv.Kind() == reflect.Ptr {
|
||||
return json.Unmarshal(paramsBytes, rv.Interface())
|
||||
}
|
||||
} else {
|
||||
return json.Unmarshal(paramsBytes, pointer)
|
||||
}
|
||||
}
|
||||
}
|
||||
// Params and its element type check.
|
||||
var (
|
||||
paramsRv reflect.Value
|
||||
paramsKind reflect.Kind
|
||||
)
|
||||
if v, ok := params.(reflect.Value); ok {
|
||||
paramsRv = v
|
||||
} else {
|
||||
paramsRv = reflect.ValueOf(params)
|
||||
}
|
||||
paramsKind = paramsRv.Kind()
|
||||
if paramsKind == reflect.Ptr {
|
||||
paramsRv = paramsRv.Elem()
|
||||
paramsKind = paramsRv.Kind()
|
||||
}
|
||||
if paramsKind != reflect.Array && paramsKind != reflect.Slice {
|
||||
return gerror.New("params should be type of slice, eg: []map/[]*map/[]struct/[]*struct")
|
||||
}
|
||||
var (
|
||||
paramsElem = paramsRv.Type().Elem()
|
||||
paramsElemKind = paramsElem.Kind()
|
||||
)
|
||||
if paramsElemKind == reflect.Ptr {
|
||||
paramsElem = paramsElem.Elem()
|
||||
paramsElemKind = paramsElem.Kind()
|
||||
}
|
||||
if paramsElemKind != reflect.Map && paramsElemKind != reflect.Struct && paramsElemKind != reflect.Interface {
|
||||
return gerror.Newf("params element should be type of map/*map/struct/*struct, but got: %s", paramsElemKind)
|
||||
}
|
||||
// Empty slice, no need continue.
|
||||
if paramsRv.Len() == 0 {
|
||||
return nil
|
||||
}
|
||||
// Pointer and its element type check.
|
||||
var (
|
||||
pointerRv = reflect.ValueOf(pointer)
|
||||
pointerKind = pointerRv.Kind()
|
||||
)
|
||||
for pointerKind == reflect.Ptr {
|
||||
pointerRv = pointerRv.Elem()
|
||||
pointerKind = pointerRv.Kind()
|
||||
}
|
||||
if pointerKind != reflect.Array && pointerKind != reflect.Slice {
|
||||
return gerror.New("pointer should be type of *[]map/*[]*map")
|
||||
}
|
||||
var (
|
||||
pointerElemType = pointerRv.Type().Elem()
|
||||
pointerElemKind = pointerElemType.Kind()
|
||||
)
|
||||
if pointerElemKind == reflect.Ptr {
|
||||
pointerElemKind = pointerElemType.Elem().Kind()
|
||||
}
|
||||
if pointerElemKind != reflect.Map {
|
||||
return gerror.New("pointer element should be type of map/*map")
|
||||
}
|
||||
defer func() {
|
||||
// Catch the panic, especially the reflect operation panics.
|
||||
if exception := recover(); exception != nil {
|
||||
if e, ok := exception.(errorStack); ok {
|
||||
err = e
|
||||
} else {
|
||||
err = gerror.NewSkipf(1, "%v", exception)
|
||||
}
|
||||
}
|
||||
}()
|
||||
var (
|
||||
pointerSlice = reflect.MakeSlice(pointerRv.Type(), paramsRv.Len(), paramsRv.Len())
|
||||
)
|
||||
for i := 0; i < paramsRv.Len(); i++ {
|
||||
var item reflect.Value
|
||||
if pointerElemType.Kind() == reflect.Ptr {
|
||||
item = reflect.New(pointerElemType.Elem())
|
||||
if err = MapToMap(paramsRv.Index(i).Interface(), item, mapping...); err != nil {
|
||||
return err
|
||||
}
|
||||
pointerSlice.Index(i).Set(item)
|
||||
} else {
|
||||
item = reflect.New(pointerElemType)
|
||||
if err = MapToMap(paramsRv.Index(i).Interface(), item, mapping...); err != nil {
|
||||
return err
|
||||
}
|
||||
pointerSlice.Index(i).Set(item.Elem())
|
||||
}
|
||||
}
|
||||
pointerRv.Set(pointerSlice)
|
||||
return
|
||||
}
|
@ -11,18 +11,39 @@ import (
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// Scan automatically calls Struct or Structs function according to the type of parameter
|
||||
// <pointer> to implement the converting.
|
||||
// It calls function Struct if <pointer> is type of *struct/**struct to do the converting.
|
||||
// It calls function Structs if <pointer> is type of *[]struct/*[]*struct to do the converting.
|
||||
// Scan automatically calls MapToMap, MapToMaps, Struct or Structs function according to
|
||||
// the type of parameter `pointer` to implement the converting.
|
||||
// It calls function MapToMap if `pointer` is type of *map to do the converting.
|
||||
// It calls function MapToMaps if `pointer` is type of *[]map/*[]*map to do the converting.
|
||||
// It calls function Struct if `pointer` is type of *struct/**struct to do the converting.
|
||||
// It calls function Structs if `pointer` is type of *[]struct/*[]*struct to do the converting.
|
||||
func Scan(params interface{}, pointer interface{}, mapping ...map[string]string) (err error) {
|
||||
t := reflect.TypeOf(pointer)
|
||||
k := t.Kind()
|
||||
if k != reflect.Ptr {
|
||||
return gerror.Newf("params should be type of pointer, but got: %v", k)
|
||||
var (
|
||||
pointerType = reflect.TypeOf(pointer)
|
||||
pointerKind = pointerType.Kind()
|
||||
)
|
||||
if pointerKind != reflect.Ptr {
|
||||
return gerror.Newf("params should be type of pointer, but got: %v", pointerKind)
|
||||
}
|
||||
switch t.Elem().Kind() {
|
||||
var (
|
||||
pointerElem = pointerType.Elem()
|
||||
pointerElemKind = pointerElem.Kind()
|
||||
)
|
||||
switch pointerElemKind {
|
||||
case reflect.Map:
|
||||
return MapToMap(params, pointer, mapping...)
|
||||
case reflect.Array, reflect.Slice:
|
||||
var (
|
||||
sliceElem = pointerElem.Elem()
|
||||
sliceElemKind = sliceElem.Kind()
|
||||
)
|
||||
for sliceElemKind == reflect.Ptr {
|
||||
sliceElem = sliceElem.Elem()
|
||||
sliceElemKind = sliceElem.Kind()
|
||||
}
|
||||
if sliceElemKind == reflect.Map {
|
||||
return MapToMaps(params, pointer, mapping...)
|
||||
}
|
||||
return Structs(params, pointer, mapping...)
|
||||
default:
|
||||
return Struct(params, pointer, mapping...)
|
||||
@ -30,9 +51,9 @@ func Scan(params interface{}, pointer interface{}, mapping ...map[string]string)
|
||||
}
|
||||
|
||||
// ScanDeep automatically calls StructDeep or StructsDeep function according to the type of
|
||||
// parameter <pointer> to implement the converting..
|
||||
// It calls function StructDeep if <pointer> is type of *struct/**struct to do the converting.
|
||||
// It calls function StructsDeep if <pointer> is type of *[]struct/*[]*struct to do the converting.
|
||||
// parameter `pointer` to implement the converting..
|
||||
// It calls function StructDeep if `pointer` is type of *struct/**struct to do the converting.
|
||||
// It calls function StructsDeep if `pointer` is type of *[]struct/*[]*struct to do the converting.
|
||||
// Deprecated, use Scan instead.
|
||||
func ScanDeep(params interface{}, pointer interface{}, mapping ...map[string]string) (err error) {
|
||||
t := reflect.TypeOf(pointer)
|
||||
|
@ -5,123 +5,3 @@
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
package gconv
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/internal/json"
|
||||
)
|
||||
|
||||
// SliceMap is alias of Maps.
|
||||
func SliceMap(any interface{}) []map[string]interface{} {
|
||||
return Maps(any)
|
||||
}
|
||||
|
||||
// SliceMapDeep is alias of MapsDeep.
|
||||
func SliceMapDeep(any interface{}) []map[string]interface{} {
|
||||
return MapsDeep(any)
|
||||
}
|
||||
|
||||
// SliceStruct is alias of Structs.
|
||||
func SliceStruct(params interface{}, pointer interface{}, mapping ...map[string]string) (err error) {
|
||||
return Structs(params, pointer, mapping...)
|
||||
}
|
||||
|
||||
// SliceStructDeep is alias of StructsDeep.
|
||||
// Deprecated, use SliceStruct instead.
|
||||
func SliceStructDeep(params interface{}, pointer interface{}, mapping ...map[string]string) (err error) {
|
||||
return StructsDeep(params, pointer, mapping...)
|
||||
}
|
||||
|
||||
// Maps converts <i> to []map[string]interface{}.
|
||||
// Note that it automatically checks and converts json string to []map if <value> is string/[]byte.
|
||||
func Maps(value interface{}, tags ...string) []map[string]interface{} {
|
||||
if value == nil {
|
||||
return nil
|
||||
}
|
||||
switch r := value.(type) {
|
||||
case string:
|
||||
list := make([]map[string]interface{}, 0)
|
||||
if len(r) > 0 && r[0] == '[' && r[len(r)-1] == ']' {
|
||||
if err := json.Unmarshal([]byte(r), &list); err != nil {
|
||||
return nil
|
||||
}
|
||||
return list
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
|
||||
case []byte:
|
||||
list := make([]map[string]interface{}, 0)
|
||||
if len(r) > 0 && r[0] == '[' && r[len(r)-1] == ']' {
|
||||
if err := json.Unmarshal(r, &list); err != nil {
|
||||
return nil
|
||||
}
|
||||
return list
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
|
||||
case []map[string]interface{}:
|
||||
return r
|
||||
|
||||
default:
|
||||
array := Interfaces(value)
|
||||
if len(array) == 0 {
|
||||
return nil
|
||||
}
|
||||
list := make([]map[string]interface{}, len(array))
|
||||
for k, v := range array {
|
||||
list[k] = Map(v, tags...)
|
||||
}
|
||||
return list
|
||||
}
|
||||
}
|
||||
|
||||
// MapsDeep converts <i> to []map[string]interface{} recursively.
|
||||
//
|
||||
// TODO completely implement the recursive converting for all types.
|
||||
func MapsDeep(value interface{}, tags ...string) []map[string]interface{} {
|
||||
if value == nil {
|
||||
return nil
|
||||
}
|
||||
switch r := value.(type) {
|
||||
case string:
|
||||
list := make([]map[string]interface{}, 0)
|
||||
if len(r) > 0 && r[0] == '[' && r[len(r)-1] == ']' {
|
||||
if err := json.Unmarshal([]byte(r), &list); err != nil {
|
||||
return nil
|
||||
}
|
||||
return list
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
|
||||
case []byte:
|
||||
list := make([]map[string]interface{}, 0)
|
||||
if len(r) > 0 && r[0] == '[' && r[len(r)-1] == ']' {
|
||||
if err := json.Unmarshal(r, &list); err != nil {
|
||||
return nil
|
||||
}
|
||||
return list
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
|
||||
case []map[string]interface{}:
|
||||
list := make([]map[string]interface{}, len(r))
|
||||
for k, v := range r {
|
||||
list[k] = MapDeep(v, tags...)
|
||||
}
|
||||
return list
|
||||
|
||||
default:
|
||||
array := Interfaces(value)
|
||||
if len(array) == 0 {
|
||||
return nil
|
||||
}
|
||||
list := make([]map[string]interface{}, len(array))
|
||||
for k, v := range array {
|
||||
list[k] = MapDeep(v, tags...)
|
||||
}
|
||||
return list
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ func SliceAny(any interface{}) []interface{} {
|
||||
return Interfaces(any)
|
||||
}
|
||||
|
||||
// Interfaces converts <i> to []interface{}.
|
||||
// Interfaces converts `i` to []interface{}.
|
||||
func Interfaces(any interface{}) []interface{} {
|
||||
if any == nil {
|
||||
return nil
|
||||
|
@ -23,12 +23,12 @@ func SliceFloat64(any interface{}) []float64 {
|
||||
return Floats(any)
|
||||
}
|
||||
|
||||
// Floats converts <i> to []float64.
|
||||
// Floats converts `i` to []float64.
|
||||
func Floats(any interface{}) []float64 {
|
||||
return Float64s(any)
|
||||
}
|
||||
|
||||
// Float32s converts <i> to []float32.
|
||||
// Float32s converts `i` to []float32.
|
||||
func Float32s(any interface{}) []float32 {
|
||||
if any == nil {
|
||||
return nil
|
||||
@ -148,7 +148,7 @@ func Float32s(any interface{}) []float32 {
|
||||
return array
|
||||
}
|
||||
|
||||
// Float64s converts <i> to []float64.
|
||||
// Float64s converts `i` to []float64.
|
||||
func Float64s(any interface{}) []float64 {
|
||||
if any == nil {
|
||||
return nil
|
||||
|
@ -23,7 +23,7 @@ func SliceInt64(any interface{}) []int64 {
|
||||
return Int64s(any)
|
||||
}
|
||||
|
||||
// Ints converts <i> to []int.
|
||||
// Ints converts `i` to []int.
|
||||
func Ints(any interface{}) []int {
|
||||
if any == nil {
|
||||
return nil
|
||||
@ -153,7 +153,7 @@ func Ints(any interface{}) []int {
|
||||
return array
|
||||
}
|
||||
|
||||
// Int32s converts <i> to []int32.
|
||||
// Int32s converts `i` to []int32.
|
||||
func Int32s(any interface{}) []int32 {
|
||||
if any == nil {
|
||||
return nil
|
||||
@ -283,7 +283,7 @@ func Int32s(any interface{}) []int32 {
|
||||
return array
|
||||
}
|
||||
|
||||
// Int64s converts <i> to []int64.
|
||||
// Int64s converts `i` to []int64.
|
||||
func Int64s(any interface{}) []int64 {
|
||||
if any == nil {
|
||||
return nil
|
||||
|
@ -13,7 +13,7 @@ func SliceStr(any interface{}) []string {
|
||||
return Strings(any)
|
||||
}
|
||||
|
||||
// Strings converts <i> to []string.
|
||||
// Strings converts `i` to []string.
|
||||
func Strings(any interface{}) []string {
|
||||
if any == nil {
|
||||
return nil
|
||||
|
@ -23,7 +23,7 @@ func SliceUint64(any interface{}) []uint64 {
|
||||
return Uint64s(any)
|
||||
}
|
||||
|
||||
// Uints converts <i> to []uint.
|
||||
// Uints converts `i` to []uint.
|
||||
func Uints(any interface{}) []uint {
|
||||
if any == nil {
|
||||
return nil
|
||||
@ -149,7 +149,7 @@ func Uints(any interface{}) []uint {
|
||||
return array
|
||||
}
|
||||
|
||||
// Uint32s converts <i> to []uint32.
|
||||
// Uint32s converts `i` to []uint32.
|
||||
func Uint32s(any interface{}) []uint32 {
|
||||
if any == nil {
|
||||
return nil
|
||||
@ -274,7 +274,7 @@ func Uint32s(any interface{}) []uint32 {
|
||||
return array
|
||||
}
|
||||
|
||||
// Uint64s converts <i> to []uint64.
|
||||
// Uint64s converts `i` to []uint64.
|
||||
func Uint64s(any interface{}) []uint64 {
|
||||
if any == nil {
|
||||
return nil
|
||||
|
@ -19,15 +19,15 @@ import (
|
||||
)
|
||||
|
||||
// Struct maps the params key-value pairs to the corresponding struct object's attributes.
|
||||
// The third parameter <mapping> is unnecessary, indicating the mapping rules between the
|
||||
// The third parameter `mapping` is unnecessary, indicating the mapping rules between the
|
||||
// custom key name and the attribute name(case sensitive).
|
||||
//
|
||||
// Note:
|
||||
// 1. The <params> can be any type of map/struct, usually a map.
|
||||
// 2. The <pointer> should be type of *struct/**struct, which is a pointer to struct object
|
||||
// 1. The `params` can be any type of map/struct, usually a map.
|
||||
// 2. The `pointer` should be type of *struct/**struct, which is a pointer to struct object
|
||||
// or struct pointer.
|
||||
// 3. Only the public attributes of struct object can be mapped.
|
||||
// 4. If <params> is a map, the key of the map <params> can be lowercase.
|
||||
// 4. If `params` is a map, the key of the map `params` can be lowercase.
|
||||
// It will automatically convert the first letter of the key to uppercase
|
||||
// in mapping procedure to do the matching.
|
||||
// It ignores the map key, if it does not match.
|
||||
@ -59,7 +59,7 @@ func StructDeep(params interface{}, pointer interface{}, mapping ...map[string]s
|
||||
// doStruct is the core internal converting function for any data to struct.
|
||||
func doStruct(params interface{}, pointer interface{}, mapping map[string]string, priorityTag string) (err error) {
|
||||
if params == nil {
|
||||
// If <params> is nil, no conversion.
|
||||
// If `params` is nil, no conversion.
|
||||
return nil
|
||||
}
|
||||
if pointer == nil {
|
||||
@ -77,7 +77,7 @@ func doStruct(params interface{}, pointer interface{}, mapping map[string]string
|
||||
}
|
||||
}()
|
||||
|
||||
// If given <params> is JSON, it then uses json.Unmarshal doing the converting.
|
||||
// If given `params` is JSON, it then uses json.Unmarshal doing the converting.
|
||||
switch r := params.(type) {
|
||||
case []byte:
|
||||
if json.Valid(r) {
|
||||
@ -140,7 +140,7 @@ func doStruct(params interface{}, pointer interface{}, mapping map[string]string
|
||||
}
|
||||
|
||||
// It automatically creates struct object if necessary.
|
||||
// For example, if <pointer> is **User, then <elem> is *User, which is a pointer to User.
|
||||
// For example, if `pointer` is **User, then `elem` is *User, which is a pointer to User.
|
||||
if pointerElemReflectValue.Kind() == reflect.Ptr {
|
||||
if !pointerElemReflectValue.IsValid() || pointerElemReflectValue.IsNil() {
|
||||
e := reflect.New(pointerElemReflectValue.Type().Elem()).Elem()
|
||||
@ -249,7 +249,7 @@ func doStruct(params interface{}, pointer interface{}, mapping map[string]string
|
||||
// string cases and chars like '-'/'_'/'.'/' '.
|
||||
|
||||
// Matching the parameters to struct tag names.
|
||||
// The <tagV> is the attribute name of the struct.
|
||||
// The `tagV` is the attribute name of the struct.
|
||||
for attrKey, cmpKey := range tagMap {
|
||||
if strings.EqualFold(checkName, cmpKey) {
|
||||
attrName = attrKey
|
||||
@ -349,7 +349,7 @@ func bindVarToReflectValueWithInterfaceCheck(reflectValue reflect.Value, value i
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// bindVarToReflectValue sets <value> to reflect value object <structFieldValue>.
|
||||
// bindVarToReflectValue sets `value` to reflect value object `structFieldValue`.
|
||||
func bindVarToReflectValue(structFieldValue reflect.Value, value interface{}, mapping map[string]string, priorityTag string) (err error) {
|
||||
if err, ok := bindVarToReflectValueWithInterfaceCheck(structFieldValue, value); ok {
|
||||
return err
|
||||
@ -455,7 +455,7 @@ func bindVarToReflectValue(structFieldValue reflect.Value, value interface{}, ma
|
||||
)
|
||||
}
|
||||
}()
|
||||
// It here uses reflect converting <value> to type of the attribute and assigns
|
||||
// It here uses reflect converting `value` to type of the attribute and assigns
|
||||
// the result value to the attribute. It might fail and panic if the usual Go
|
||||
// conversion rules do not allow conversion.
|
||||
structFieldValue.Set(reflect.ValueOf(value).Convert(structFieldValue.Type()))
|
||||
|
@ -40,14 +40,14 @@ func StructsDeep(params interface{}, pointer interface{}, mapping ...map[string]
|
||||
|
||||
// doStructs converts any slice to given struct slice.
|
||||
//
|
||||
// It automatically checks and converts json string to []map if <params> is string/[]byte.
|
||||
// It automatically checks and converts json string to []map if `params` is string/[]byte.
|
||||
//
|
||||
// The parameter <pointer> should be type of pointer to slice of struct.
|
||||
// Note that if <pointer> is a pointer to another pointer of type of slice of struct,
|
||||
// The parameter `pointer` should be type of pointer to slice of struct.
|
||||
// Note that if `pointer` is a pointer to another pointer of type of slice of struct,
|
||||
// it will create the struct/pointer internally.
|
||||
func doStructs(params interface{}, pointer interface{}, mapping map[string]string, priorityTag string) (err error) {
|
||||
if params == nil {
|
||||
// If <params> is nil, no conversion.
|
||||
// If `params` is nil, no conversion.
|
||||
return nil
|
||||
}
|
||||
if pointer == nil {
|
||||
@ -68,7 +68,7 @@ func doStructs(params interface{}, pointer interface{}, mapping map[string]strin
|
||||
}
|
||||
}
|
||||
}()
|
||||
// If given <params> is JSON, it then uses json.Unmarshal doing the converting.
|
||||
// If given `params` is JSON, it then uses json.Unmarshal doing the converting.
|
||||
switch r := params.(type) {
|
||||
case []byte:
|
||||
if json.Valid(r) {
|
||||
@ -99,9 +99,9 @@ func doStructs(params interface{}, pointer interface{}, mapping map[string]strin
|
||||
return gerror.Newf("pointer should be type of pointer, but got: %v", kind)
|
||||
}
|
||||
}
|
||||
// Converting <params> to map slice.
|
||||
// Converting `params` to map slice.
|
||||
paramsMaps := Maps(params)
|
||||
// If <params> is an empty slice, no conversion.
|
||||
// If `params` is an empty slice, no conversion.
|
||||
if len(paramsMaps) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ import (
|
||||
"github.com/gogf/gf/os/gtime"
|
||||
)
|
||||
|
||||
// Time converts <i> to time.Time.
|
||||
// Time converts `i` to time.Time.
|
||||
func Time(any interface{}, format ...string) time.Time {
|
||||
// It's already this type.
|
||||
if len(format) == 0 {
|
||||
@ -27,9 +27,9 @@ func Time(any interface{}, format ...string) time.Time {
|
||||
return time.Time{}
|
||||
}
|
||||
|
||||
// Duration converts <i> to time.Duration.
|
||||
// If <i> is string, then it uses time.ParseDuration to convert it.
|
||||
// If <i> is numeric, then it converts <i> as nanoseconds.
|
||||
// Duration converts `i` to time.Duration.
|
||||
// If `i` is string, then it uses time.ParseDuration to convert it.
|
||||
// If `i` is numeric, then it converts `i` as nanoseconds.
|
||||
func Duration(any interface{}) time.Duration {
|
||||
// It's already this type.
|
||||
if v, ok := any.(time.Duration); ok {
|
||||
@ -43,10 +43,10 @@ func Duration(any interface{}) time.Duration {
|
||||
return time.Duration(Int64(any))
|
||||
}
|
||||
|
||||
// GTime converts <i> to *gtime.Time.
|
||||
// The parameter <format> can be used to specify the format of <i>.
|
||||
// If no <format> given, it converts <i> using gtime.NewFromTimeStamp if <i> is numeric,
|
||||
// or using gtime.StrToTime if <i> is string.
|
||||
// GTime converts `i` to *gtime.Time.
|
||||
// The parameter `format` can be used to specify the format of `i`.
|
||||
// If no `format` given, it converts `i` using gtime.NewFromTimeStamp if `i` is numeric,
|
||||
// or using gtime.StrToTime if `i` is string.
|
||||
func GTime(any interface{}, format ...string) *gtime.Time {
|
||||
if any == nil {
|
||||
return nil
|
||||
|
@ -9,14 +9,14 @@ package gconv
|
||||
import "unsafe"
|
||||
|
||||
// UnsafeStrToBytes converts string to []byte without memory copy.
|
||||
// Note that, if you completely sure you will never use <s> variable in the feature,
|
||||
// Note that, if you completely sure you will never use `s` variable in the feature,
|
||||
// you can use this unsafe function to implement type conversion in high performance.
|
||||
func UnsafeStrToBytes(s string) []byte {
|
||||
return *(*[]byte)(unsafe.Pointer(&s))
|
||||
}
|
||||
|
||||
// UnsafeBytesToStr converts []byte to string without memory copy.
|
||||
// Note that, if you completely sure you will never use <b> variable in the feature,
|
||||
// Note that, if you completely sure you will never use `b` variable in the feature,
|
||||
// you can use this unsafe function to implement type conversion in high performance.
|
||||
func UnsafeBytesToStr(b []byte) string {
|
||||
return *(*string)(unsafe.Pointer(&b))
|
||||
|
@ -143,184 +143,46 @@ func Test_MapToMapDeep(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func Test_MapToMaps1(t *testing.T) {
|
||||
func Test_MapToMaps(t *testing.T) {
|
||||
params := g.Slice{
|
||||
g.Map{"id": 1, "name": "john"},
|
||||
g.Map{"id": 2, "name": "smith"},
|
||||
}
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
var s []g.Map
|
||||
err := gconv.MapToMaps(params, &s)
|
||||
t.AssertNil(err)
|
||||
t.Assert(len(s), 2)
|
||||
t.Assert(s, params)
|
||||
})
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
var s []*g.Map
|
||||
err := gconv.MapToMaps(params, &s)
|
||||
t.AssertNil(err)
|
||||
t.Assert(len(s), 2)
|
||||
t.Assert(s, params)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_MapToMaps_StructParams(t *testing.T) {
|
||||
type User struct {
|
||||
Id int
|
||||
Name int
|
||||
}
|
||||
params := g.Map{
|
||||
"key1": g.Slice{
|
||||
g.Map{"id": 1, "name": "john"},
|
||||
g.Map{"id": 2, "name": "smith"},
|
||||
},
|
||||
"key2": g.Slice{
|
||||
g.Map{"id": 3, "name": "green"},
|
||||
g.Map{"id": 4, "name": "jim"},
|
||||
},
|
||||
}
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
m := make(map[string][]User)
|
||||
err := gconv.MapToMaps(params, &m)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(len(m), 2)
|
||||
t.Assert(m["key1"][0].Id, 1)
|
||||
t.Assert(m["key1"][1].Id, 2)
|
||||
t.Assert(m["key2"][0].Id, 3)
|
||||
t.Assert(m["key2"][1].Id, 4)
|
||||
})
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
m := (map[string][]User)(nil)
|
||||
err := gconv.MapToMaps(params, &m)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(len(m), 2)
|
||||
t.Assert(m["key1"][0].Id, 1)
|
||||
t.Assert(m["key1"][1].Id, 2)
|
||||
t.Assert(m["key2"][0].Id, 3)
|
||||
t.Assert(m["key2"][1].Id, 4)
|
||||
})
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
m := make(map[string][]*User)
|
||||
err := gconv.MapToMaps(params, &m)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(len(m), 2)
|
||||
t.Assert(m["key1"][0].Id, 1)
|
||||
t.Assert(m["key1"][1].Id, 2)
|
||||
t.Assert(m["key2"][0].Id, 3)
|
||||
t.Assert(m["key2"][1].Id, 4)
|
||||
})
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
m := (map[string][]*User)(nil)
|
||||
err := gconv.MapToMaps(params, &m)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(len(m), 2)
|
||||
t.Assert(m["key1"][0].Id, 1)
|
||||
t.Assert(m["key1"][1].Id, 2)
|
||||
t.Assert(m["key2"][0].Id, 3)
|
||||
t.Assert(m["key2"][1].Id, 4)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_MapToMaps2(t *testing.T) {
|
||||
type User struct {
|
||||
Id int
|
||||
Name int
|
||||
}
|
||||
params := g.MapIntAny{
|
||||
100: g.Slice{
|
||||
g.Map{"id": 1, "name": "john"},
|
||||
g.Map{"id": 2, "name": "smith"},
|
||||
},
|
||||
200: g.Slice{
|
||||
g.Map{"id": 3, "name": "green"},
|
||||
g.Map{"id": 4, "name": "jim"},
|
||||
},
|
||||
}
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
m := make(map[int][]User)
|
||||
err := gconv.MapToMaps(params, &m)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(len(m), 2)
|
||||
t.Assert(m[100][0].Id, 1)
|
||||
t.Assert(m[100][1].Id, 2)
|
||||
t.Assert(m[200][0].Id, 3)
|
||||
t.Assert(m[200][1].Id, 4)
|
||||
})
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
m := make(map[int][]*User)
|
||||
err := gconv.MapToMaps(params, &m)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(len(m), 2)
|
||||
t.Assert(m[100][0].Id, 1)
|
||||
t.Assert(m[100][1].Id, 2)
|
||||
t.Assert(m[200][0].Id, 3)
|
||||
t.Assert(m[200][1].Id, 4)
|
||||
})
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
m := make(map[string][]*User)
|
||||
err := gconv.MapToMaps(params, &m)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(len(m), 2)
|
||||
t.Assert(m["100"][0].Id, 1)
|
||||
t.Assert(m["100"][1].Id, 2)
|
||||
t.Assert(m["200"][0].Id, 3)
|
||||
t.Assert(m["200"][1].Id, 4)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_MapToMaps3(t *testing.T) {
|
||||
type Ids struct {
|
||||
Id int
|
||||
Uid int
|
||||
}
|
||||
type Base struct {
|
||||
Ids
|
||||
Time string
|
||||
}
|
||||
type User struct {
|
||||
Base
|
||||
Name string
|
||||
}
|
||||
params := g.MapIntAny{
|
||||
100: g.Slice{
|
||||
g.Map{"id": 1, "name": "john"},
|
||||
g.Map{"id": 2, "name": "smith"},
|
||||
},
|
||||
200: g.Slice{
|
||||
g.Map{"id": 3, "name": "green"},
|
||||
g.Map{"id": 4, "name": "jim"},
|
||||
},
|
||||
params := g.Slice{
|
||||
User{1, "name1"},
|
||||
User{2, "name2"},
|
||||
}
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
m := make(map[string][]*User)
|
||||
err := gconv.MapToMaps(params, &m)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(len(m), 2)
|
||||
t.Assert(m["100"][0].Id, 1)
|
||||
t.Assert(m["100"][1].Id, 2)
|
||||
t.Assert(m["100"][0].Name, "john")
|
||||
t.Assert(m["100"][1].Name, "smith")
|
||||
t.Assert(m["200"][0].Id, 3)
|
||||
t.Assert(m["200"][1].Id, 4)
|
||||
t.Assert(m["200"][0].Name, "green")
|
||||
t.Assert(m["200"][1].Name, "jim")
|
||||
var s []g.Map
|
||||
err := gconv.MapToMaps(params, &s)
|
||||
t.AssertNil(err)
|
||||
t.Assert(len(s), 2)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_MapToMapsWithTag(t *testing.T) {
|
||||
type Ids struct {
|
||||
Id int
|
||||
Uid int
|
||||
}
|
||||
type Base struct {
|
||||
Ids `json:"ids"`
|
||||
Time string
|
||||
}
|
||||
type User struct {
|
||||
Base `json:"base"`
|
||||
Name string
|
||||
}
|
||||
params := g.MapIntAny{
|
||||
100: g.Slice{
|
||||
g.Map{"id": 1, "name": "john"},
|
||||
g.Map{"id": 2, "name": "smith"},
|
||||
},
|
||||
200: g.Slice{
|
||||
g.Map{"id": 3, "name": "green"},
|
||||
g.Map{"id": 4, "name": "jim"},
|
||||
},
|
||||
}
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
m := make(map[string][]*User)
|
||||
err := gconv.MapToMaps(params, &m)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(len(m), 2)
|
||||
t.Assert(m["100"][0].Id, 1)
|
||||
t.Assert(m["100"][1].Id, 2)
|
||||
t.Assert(m["100"][0].Name, "john")
|
||||
t.Assert(m["100"][1].Name, "smith")
|
||||
t.Assert(m["200"][0].Id, 3)
|
||||
t.Assert(m["200"][1].Id, 4)
|
||||
t.Assert(m["200"][0].Name, "green")
|
||||
t.Assert(m["200"][1].Name, "jim")
|
||||
var s []*g.Map
|
||||
err := gconv.MapToMaps(params, &s)
|
||||
t.AssertNil(err)
|
||||
t.Assert(len(s), 2)
|
||||
})
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test_Scan(t *testing.T) {
|
||||
func Test_Scan_StructStructs(t *testing.T) {
|
||||
type User struct {
|
||||
Uid int
|
||||
Name string
|
||||
@ -76,7 +76,7 @@ func Test_Scan(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func Test_ScanStr(t *testing.T) {
|
||||
func Test_Scan_StructStr(t *testing.T) {
|
||||
type User struct {
|
||||
Uid int
|
||||
Name string
|
||||
@ -123,3 +123,73 @@ func Test_ScanStr(t *testing.T) {
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Scan_Map(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
var m map[string]string
|
||||
data := g.Map{
|
||||
"k1": "v1",
|
||||
"k2": "v2",
|
||||
}
|
||||
err := gconv.Scan(data, &m)
|
||||
t.AssertNil(err)
|
||||
t.Assert(data, m)
|
||||
})
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
var m map[int]int
|
||||
data := g.Map{
|
||||
"1": "11",
|
||||
"2": "22",
|
||||
}
|
||||
err := gconv.Scan(data, &m)
|
||||
t.AssertNil(err)
|
||||
t.Assert(data, m)
|
||||
})
|
||||
// json string parameter.
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
var m map[string]string
|
||||
data := `{"k1":"v1","k2":"v2"}`
|
||||
err := gconv.Scan(data, &m)
|
||||
t.AssertNil(err)
|
||||
t.Assert(m, g.Map{
|
||||
"k1": "v1",
|
||||
"k2": "v2",
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Scan_Maps(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
var maps []map[string]string
|
||||
data := g.Slice{
|
||||
g.Map{
|
||||
"k1": "v1",
|
||||
"k2": "v2",
|
||||
},
|
||||
g.Map{
|
||||
"k3": "v3",
|
||||
"k4": "v4",
|
||||
},
|
||||
}
|
||||
err := gconv.Scan(data, &maps)
|
||||
t.AssertNil(err)
|
||||
t.Assert(data, maps)
|
||||
})
|
||||
// json string parameter.
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
var maps []map[string]string
|
||||
data := `[{"k1":"v1","k2":"v2"},{"k3":"v3","k4":"v4"}]`
|
||||
err := gconv.Scan(data, &maps)
|
||||
t.AssertNil(err)
|
||||
t.Assert(maps, g.Slice{
|
||||
g.Map{
|
||||
"k1": "v1",
|
||||
"k2": "v2",
|
||||
},
|
||||
g.Map{
|
||||
"k3": "v3",
|
||||
"k4": "v4",
|
||||
},
|
||||
})
|
||||
})
|
||||
}
|
||||
|
@ -21,9 +21,9 @@ type Page struct {
|
||||
TotalPage int // Total page, which is automatically calculated.
|
||||
CurrentPage int // Current page number >= 1.
|
||||
UrlTemplate string // Custom url template for page url producing.
|
||||
LinkStyle string // CSS style name for HTML link tag <a>.
|
||||
SpanStyle string // CSS style name for HTML span tag <span>, which is used for first, current and last page tag.
|
||||
SelectStyle string // CSS style name for HTML select tag <select>.
|
||||
LinkStyle string // CSS style name for HTML link tag `a`.
|
||||
SpanStyle string // CSS style name for HTML span tag `span`, which is used for first, current and last page tag.
|
||||
SelectStyle string // CSS style name for HTML select tag `select`.
|
||||
NextPageTag string // Tag name for next p.
|
||||
PrevPageTag string // Tag name for prev p.
|
||||
FirstPageTag string // Tag name for first p.
|
||||
@ -40,9 +40,9 @@ const (
|
||||
)
|
||||
|
||||
// New creates and returns a pagination manager.
|
||||
// Note that the parameter <urlTemplate> specifies the URL producing template, like:
|
||||
// Note that the parameter `urlTemplate` specifies the URL producing template, like:
|
||||
// /user/list/{.page}, /user/list/{.page}.html, /user/list?page={.page}&type=1, etc.
|
||||
// The build-in variable in <urlTemplate> "{.page}" specifies the page number, which will be replaced by certain
|
||||
// The build-in variable in `urlTemplate` "{.page}" specifies the page number, which will be replaced by certain
|
||||
// page number when producing.
|
||||
func New(totalSize, pageSize, currentPage int, urlTemplate string) *Page {
|
||||
p := &Page{
|
||||
@ -209,7 +209,7 @@ func (p *Page) GetUrl(page int) string {
|
||||
return gstr.Replace(p.UrlTemplate, PAGE_PLACE_HOLDER, gconv.String(page))
|
||||
}
|
||||
|
||||
// GetLink returns the HTML link tag <a> content for given page number.
|
||||
// GetLink returns the HTML link tag `a` content for given page number.
|
||||
func (p *Page) GetLink(page int, text, title string) string {
|
||||
if len(p.AjaxActionName) > 0 {
|
||||
return fmt.Sprintf(
|
||||
|
@ -109,7 +109,7 @@ func Test_PredefinedContent(t *testing.T) {
|
||||
page.AjaxActionName = "LoadPage"
|
||||
t.Assert(page.GetContent(1), `<a class="GPageLink" href="javascript:LoadPage('/user/list/1')" title="">上一页</a> <span class="current">2</span> <a class="GPageLink" href="javascript:LoadPage('/user/list/3')" title="">下一页</a>`)
|
||||
t.Assert(page.GetContent(2), `<a class="GPageLink" href="javascript:LoadPage('/user/list/1')" title="">首页</a><a class="GPageLink" href="javascript:LoadPage('/user/list/1')" title=""><<上一页</a><span class="current">[第2页]</span><a class="GPageLink" href="javascript:LoadPage('/user/list/3')" title="">下一页>></a><a class="GPageLink" href="javascript:LoadPage('/user/list/5')" title="">尾页</a>第<select name="GPageSelect" onchange="window.location.href=this.value"><option value="/user/list/1">1</option><option value="/user/list/2" selected>2</option><option value="/user/list/3">3</option><option value="/user/list/4">4</option><option value="/user/list/5">5</option></select>页`)
|
||||
t.Assert(page.GetContent(3), `<a class="GPageLink" href="javascript:LoadPage('/user/list/1')" title="">首页</a><a class="GPageLink" href="javascript:LoadPage('/user/list/1')" title="">上一页</a><a class="GPageLink" href="javascript:LoadPage('/user/list/1')" title="1">1</a><span class="GPageSpan">2</span><a class="GPageLink" href="javascript:LoadPage('/user/list/3')" title="3">3</a><a class="GPageLink" href="javascript:LoadPage('/user/list/4')" title="4">4</a><a class="GPageLink" href="javascript:LoadPage('/user/list/5')" title="5">5</a><a class="GPageLink" href="javascript:LoadPage('/user/list/3')" title="">下一页</a><a class="GPageLink" href="javascript:LoadPage('/user/list/5')" title="">尾页</a><span>当前页2/5</span> <span>共5条</span>`)
|
||||
t.Assert(page.GetContent(3), `<a class="GPageLink" href="javascript:LoadPage('/user/list/1')" title="">首页</a><a class="GPageLink" href="javascript:LoadPage('/user/list/1')" title="">上一页</a><a class="GPageLink" href="javascript:LoadPage('/user/list/1')" title="1">1</a><span class="GPageSpan">2</span><a class="GPageLink" href="javascript:LoadPage('/user/list/3')" title="3">3</a><a class="GPageLink" href="javascript:LoadPage('/user/list/4')" title="4">4</a><a class="GPageLink" href="javascript:LoadPage('/user/list/5')" title="5">5</a><a class="GPageLink" href="javascript:LoadPage('/user/list/3')" title="">下一页</a><a class="GPageLink" href="javascript:LoadPage('/user/list/5')" title="">尾页</a>`span`当前页2/5</span> `span`共5条</span>`)
|
||||
t.Assert(page.GetContent(4), `<a class="GPageLink" href="javascript:LoadPage('/user/list/1')" title="">首页</a><a class="GPageLink" href="javascript:LoadPage('/user/list/1')" title="">上一页</a><a class="GPageLink" href="javascript:LoadPage('/user/list/1')" title="1">1</a><span class="GPageSpan">2</span><a class="GPageLink" href="javascript:LoadPage('/user/list/3')" title="3">3</a><a class="GPageLink" href="javascript:LoadPage('/user/list/4')" title="4">4</a><a class="GPageLink" href="javascript:LoadPage('/user/list/5')" title="5">5</a><a class="GPageLink" href="javascript:LoadPage('/user/list/3')" title="">下一页</a><a class="GPageLink" href="javascript:LoadPage('/user/list/5')" title="">尾页</a>`)
|
||||
t.Assert(page.GetContent(5), ``)
|
||||
})
|
||||
|
@ -23,8 +23,8 @@ var (
|
||||
// Intn returns a int number which is between 0 and max: [0, max).
|
||||
//
|
||||
// Note that:
|
||||
// 1. The <max> can only be greater than 0, or else it returns <max> directly;
|
||||
// 2. The result is greater than or equal to 0, but less than <max>;
|
||||
// 1. The `max` can only be greater than 0, or else it returns `max` directly;
|
||||
// 2. The result is greater than or equal to 0, but less than `max`;
|
||||
// 3. The result number is 32bit and less than math.MaxUint32.
|
||||
func Intn(max int) int {
|
||||
if max <= 0 {
|
||||
@ -37,7 +37,7 @@ func Intn(max int) int {
|
||||
return n
|
||||
}
|
||||
|
||||
// B retrieves and returns random bytes of given length <n>.
|
||||
// B retrieves and returns random bytes of given length `n`.
|
||||
func B(n int) []byte {
|
||||
if n <= 0 {
|
||||
return nil
|
||||
@ -55,7 +55,7 @@ func B(n int) []byte {
|
||||
}
|
||||
|
||||
// N returns a random int between min and max: [min, max].
|
||||
// The <min> and <max> also support negative numbers.
|
||||
// The `min` and `max` also support negative numbers.
|
||||
func N(min, max int) int {
|
||||
if min >= max {
|
||||
return min
|
||||
@ -77,8 +77,8 @@ func N(min, max int) int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// S returns a random string which contains digits and letters, and its length is <n>.
|
||||
// The optional parameter <symbols> specifies whether the result could contain symbols,
|
||||
// S returns a random string which contains digits and letters, and its length is `n`.
|
||||
// The optional parameter `symbols` specifies whether the result could contain symbols,
|
||||
// which is false in default.
|
||||
func S(n int, symbols ...bool) string {
|
||||
if n <= 0 {
|
||||
@ -112,7 +112,7 @@ func D(min, max time.Duration) time.Duration {
|
||||
return time.Duration(n * multiple)
|
||||
}
|
||||
|
||||
// Str randomly picks and returns <n> count of chars from given string <s>.
|
||||
// Str randomly picks and returns `n` count of chars from given string `s`.
|
||||
// It also supports unicode string like Chinese/Russian/Japanese, etc.
|
||||
func Str(s string, n int) string {
|
||||
if n <= 0 {
|
||||
@ -135,7 +135,7 @@ func Str(s string, n int) string {
|
||||
return string(b)
|
||||
}
|
||||
|
||||
// Digits returns a random string which contains only digits, and its length is <n>.
|
||||
// Digits returns a random string which contains only digits, and its length is `n`.
|
||||
func Digits(n int) string {
|
||||
if n <= 0 {
|
||||
return ""
|
||||
@ -150,7 +150,7 @@ func Digits(n int) string {
|
||||
return *(*string)(unsafe.Pointer(&b))
|
||||
}
|
||||
|
||||
// Letters returns a random string which contains only letters, and its length is <n>.
|
||||
// Letters returns a random string which contains only letters, and its length is `n`.
|
||||
func Letters(n int) string {
|
||||
if n <= 0 {
|
||||
return ""
|
||||
@ -165,7 +165,7 @@ func Letters(n int) string {
|
||||
return *(*string)(unsafe.Pointer(&b))
|
||||
}
|
||||
|
||||
// Symbols returns a random string which contains only symbols, and its length is <n>.
|
||||
// Symbols returns a random string which contains only symbols, and its length is `n`.
|
||||
func Symbols(n int) string {
|
||||
if n <= 0 {
|
||||
return ""
|
||||
@ -192,7 +192,7 @@ func Perm(n int) []int {
|
||||
return m
|
||||
}
|
||||
|
||||
// Meet randomly calculate whether the given probability <num>/<total> is met.
|
||||
// Meet randomly calculate whether the given probability `num`/`total` is met.
|
||||
func Meet(num, total int) bool {
|
||||
return Intn(total) < num
|
||||
}
|
||||
|
@ -50,11 +50,11 @@ func init() {
|
||||
|
||||
// S creates and returns a global unique string in 32 bytes that meets most common
|
||||
// usages without strict UUID algorithm. It returns an unique string using default
|
||||
// unique algorithm if no <data> is given.
|
||||
// unique algorithm if no `data` is given.
|
||||
//
|
||||
// The specified <data> can be no more than 2 parts. No matter how long each of the
|
||||
// <data> size is, each of them will be hashed into 7 bytes as part of the result.
|
||||
// If given <data> parts is less than 2, the leftover size of the result bytes will
|
||||
// The specified `data` can be no more than 2 parts. No matter how long each of the
|
||||
// `data` size is, each of them will be hashed into 7 bytes as part of the result.
|
||||
// If given `data` parts is less than 2, the leftover size of the result bytes will
|
||||
// be token by random string.
|
||||
//
|
||||
// The returned string is composed with:
|
||||
@ -63,7 +63,7 @@ func init() {
|
||||
//
|
||||
// Note that:
|
||||
// 1. The returned length is fixed to 32 bytes for performance purpose.
|
||||
// 2. The custom parameter <data> composed should have unique attribute in your
|
||||
// 2. The custom parameter `data` composed should have unique attribute in your
|
||||
// business situation.
|
||||
func S(data ...[]byte) string {
|
||||
var (
|
||||
@ -103,7 +103,7 @@ func getSequence() []byte {
|
||||
return b
|
||||
}
|
||||
|
||||
// getRandomStr randomly picks and returns <n> count of chars from randomStrBase.
|
||||
// getRandomStr randomly picks and returns `n` count of chars from randomStrBase.
|
||||
func getRandomStr(n int) []byte {
|
||||
if n <= 0 {
|
||||
return []byte{}
|
||||
|
@ -32,7 +32,7 @@ func Try(try func()) (err error) {
|
||||
}
|
||||
|
||||
// TryCatch implements try...catch... logistics using internal panic...recover.
|
||||
// It automatically calls function <catch> if any exception occurs ans passes the exception as an error.
|
||||
// It automatically calls function `catch` if any exception occurs ans passes the exception as an error.
|
||||
func TryCatch(try func(), catch ...func(exception error)) {
|
||||
defer func() {
|
||||
if exception := recover(); exception != nil && len(catch) > 0 {
|
||||
@ -46,8 +46,8 @@ func TryCatch(try func(), catch ...func(exception error)) {
|
||||
try()
|
||||
}
|
||||
|
||||
// IsEmpty checks given <value> empty or not.
|
||||
// It returns false if <value> is: integer(0), bool(false), slice/map(len=0), nil;
|
||||
// IsEmpty checks given `value` empty or not.
|
||||
// It returns false if `value` is: integer(0), bool(false), slice/map(len=0), nil;
|
||||
// or else returns true.
|
||||
func IsEmpty(value interface{}) bool {
|
||||
return empty.IsEmpty(value)
|
||||
|
@ -10,16 +10,16 @@ import (
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// ListItemValues retrieves and returns the elements of all item struct/map with key <key>.
|
||||
// Note that the parameter <list> should be type of slice which contains elements of map or struct,
|
||||
// ListItemValues retrieves and returns the elements of all item struct/map with key `key`.
|
||||
// Note that the parameter `list` should be type of slice which contains elements of map or struct,
|
||||
// or else it returns an empty slice.
|
||||
//
|
||||
// The parameter <list> supports types like:
|
||||
// The parameter `list` supports types like:
|
||||
// []map[string]interface{}
|
||||
// []map[string]sub-map
|
||||
// []struct
|
||||
// []struct:sub-struct
|
||||
// Note that the sub-map/sub-struct makes sense only if the optional parameter <subKey> is given.
|
||||
// Note that the sub-map/sub-struct makes sense only if the optional parameter `subKey` is given.
|
||||
func ListItemValues(list interface{}, key interface{}, subKey ...interface{}) (values []interface{}) {
|
||||
var reflectValue reflect.Value
|
||||
if v, ok := list.(reflect.Value); ok {
|
||||
@ -58,8 +58,8 @@ func ListItemValues(list interface{}, key interface{}, subKey ...interface{}) (v
|
||||
return
|
||||
}
|
||||
|
||||
// ItemValue retrieves and returns its value of which name/attribute specified by <key>.
|
||||
// The parameter <item> can be type of map/*map/struct/*struct.
|
||||
// ItemValue retrieves and returns its value of which name/attribute specified by `key`.
|
||||
// The parameter `item` can be type of map/*map/struct/*struct.
|
||||
func ItemValue(item interface{}, key interface{}) (value interface{}, found bool) {
|
||||
var reflectValue reflect.Value
|
||||
if v, ok := item.(reflect.Value); ok {
|
||||
@ -84,7 +84,7 @@ func ItemValue(item interface{}, key interface{}) (value interface{}, found bool
|
||||
}
|
||||
switch reflectKind {
|
||||
case reflect.Array, reflect.Slice:
|
||||
// The <key> must be type of string.
|
||||
// The `key` must be type of string.
|
||||
values := ListItemValues(reflectValue, keyValue.String())
|
||||
if values == nil {
|
||||
return nil, false
|
||||
@ -99,7 +99,7 @@ func ItemValue(item interface{}, key interface{}) (value interface{}, found bool
|
||||
}
|
||||
|
||||
case reflect.Struct:
|
||||
// The <mapKey> must be type of string.
|
||||
// The `mapKey` must be type of string.
|
||||
v := reflectValue.FieldByName(keyValue.String())
|
||||
if v.IsValid() {
|
||||
found = true
|
||||
@ -109,8 +109,8 @@ func ItemValue(item interface{}, key interface{}) (value interface{}, found bool
|
||||
return
|
||||
}
|
||||
|
||||
// ListItemValuesUnique retrieves and returns the unique elements of all struct/map with key <key>.
|
||||
// Note that the parameter <list> should be type of slice which contains elements of map or struct,
|
||||
// ListItemValuesUnique retrieves and returns the unique elements of all struct/map with key `key`.
|
||||
// Note that the parameter `list` should be type of slice which contains elements of map or struct,
|
||||
// or else it returns an empty slice.
|
||||
func ListItemValuesUnique(list interface{}, key string, subKey ...interface{}) []interface{} {
|
||||
values := ListItemValues(list, key, subKey...)
|
||||
|
@ -11,7 +11,7 @@ import (
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// MapCopy does a shallow copy from map <data> to <copy> for most commonly used map type
|
||||
// MapCopy does a shallow copy from map `data` to `copy` for most commonly used map type
|
||||
// map[string]interface{}.
|
||||
func MapCopy(data map[string]interface{}) (copy map[string]interface{}) {
|
||||
copy = make(map[string]interface{}, len(data))
|
||||
@ -21,7 +21,7 @@ func MapCopy(data map[string]interface{}) (copy map[string]interface{}) {
|
||||
return
|
||||
}
|
||||
|
||||
// MapContains checks whether map <data> contains <key>.
|
||||
// MapContains checks whether map `data` contains `key`.
|
||||
func MapContains(data map[string]interface{}, key string) (ok bool) {
|
||||
if len(data) == 0 {
|
||||
return
|
||||
@ -30,7 +30,7 @@ func MapContains(data map[string]interface{}, key string) (ok bool) {
|
||||
return
|
||||
}
|
||||
|
||||
// MapDelete deletes all <keys> from map <data>.
|
||||
// MapDelete deletes all `keys` from map `data`.
|
||||
func MapDelete(data map[string]interface{}, keys ...string) {
|
||||
if len(data) == 0 {
|
||||
return
|
||||
@ -40,7 +40,7 @@ func MapDelete(data map[string]interface{}, keys ...string) {
|
||||
}
|
||||
}
|
||||
|
||||
// MapMerge merges all map from <src> to map <dst>.
|
||||
// MapMerge merges all map from `src` to map `dst`.
|
||||
func MapMerge(dst map[string]interface{}, src ...map[string]interface{}) {
|
||||
if dst == nil {
|
||||
return
|
||||
@ -52,7 +52,7 @@ func MapMerge(dst map[string]interface{}, src ...map[string]interface{}) {
|
||||
}
|
||||
}
|
||||
|
||||
// MapMergeCopy creates and returns a new map which merges all map from <src>.
|
||||
// MapMergeCopy creates and returns a new map which merges all map from `src`.
|
||||
func MapMergeCopy(src ...map[string]interface{}) (copy map[string]interface{}) {
|
||||
copy = make(map[string]interface{})
|
||||
for _, m := range src {
|
||||
@ -82,7 +82,7 @@ func MapPossibleItemByKey(data map[string]interface{}, key string) (foundKey str
|
||||
return "", nil
|
||||
}
|
||||
|
||||
// MapContainsPossibleKey checks if the given <key> is contained in given map <data>.
|
||||
// MapContainsPossibleKey checks if the given `key` is contained in given map `data`.
|
||||
// It checks the key ignoring cases and symbols.
|
||||
//
|
||||
// Note that this function might be of low performance.
|
||||
|
@ -11,7 +11,7 @@ import (
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// SliceCopy does a shallow copy of slice <data> for most commonly used slice type
|
||||
// SliceCopy does a shallow copy of slice `data` for most commonly used slice type
|
||||
// []interface{}.
|
||||
func SliceCopy(data []interface{}) []interface{} {
|
||||
newData := make([]interface{}, len(data))
|
||||
@ -19,8 +19,8 @@ func SliceCopy(data []interface{}) []interface{} {
|
||||
return newData
|
||||
}
|
||||
|
||||
// SliceDelete deletes an element at <index> and returns the new slice.
|
||||
// It does nothing if the given <index> is invalid.
|
||||
// SliceDelete deletes an element at `index` and returns the new slice.
|
||||
// It does nothing if the given `index` is invalid.
|
||||
func SliceDelete(data []interface{}, index int) (newSlice []interface{}) {
|
||||
if index < 0 || index >= len(data) {
|
||||
return data
|
||||
|
@ -163,12 +163,12 @@ var (
|
||||
// Check checks single value with specified rules.
|
||||
// It returns nil if successful validation.
|
||||
//
|
||||
// The parameter <value> can be any type of variable, which will be converted to string
|
||||
// The parameter `value` can be any type of variable, which will be converted to string
|
||||
// for validation.
|
||||
// The parameter <rules> can be one or more rules, multiple rules joined using char '|'.
|
||||
// The parameter <messages> specifies the custom error messages, which can be type of:
|
||||
// The parameter `rules` can be one or more rules, multiple rules joined using char '|'.
|
||||
// The parameter `messages` specifies the custom error messages, which can be type of:
|
||||
// string/map/struct/*struct.
|
||||
// The optional parameter <params> specifies the extra validation parameters for some rules
|
||||
// The optional parameter `params` specifies the extra validation parameters for some rules
|
||||
// like: required-*、same、different, etc.
|
||||
func Check(value interface{}, rules string, messages interface{}, params ...interface{}) *Error {
|
||||
return defaultValidator.Check(value, rules, messages, params...)
|
||||
@ -176,19 +176,19 @@ func Check(value interface{}, rules string, messages interface{}, params ...inte
|
||||
|
||||
// CheckMap validates map and returns the error result. It returns nil if with successful validation.
|
||||
//
|
||||
// The parameter <rules> can be type of []string/map[string]string. It supports sequence in error result
|
||||
// if <rules> is type of []string.
|
||||
// The optional parameter <messages> specifies the custom error messages for specified keys and rules.
|
||||
// The parameter `rules` can be type of []string/map[string]string. It supports sequence in error result
|
||||
// if `rules` is type of []string.
|
||||
// The optional parameter `messages` specifies the custom error messages for specified keys and rules.
|
||||
func CheckMap(params interface{}, rules interface{}, messages ...CustomMsg) *Error {
|
||||
return defaultValidator.CheckMap(params, rules, messages...)
|
||||
}
|
||||
|
||||
// CheckStruct validates strcut and returns the error result.
|
||||
//
|
||||
// The parameter <object> should be type of struct/*struct.
|
||||
// The parameter <rules> can be type of []string/map[string]string. It supports sequence in error result
|
||||
// if <rules> is type of []string.
|
||||
// The optional parameter <messages> specifies the custom error messages for specified keys and rules.
|
||||
// The parameter `object` should be type of struct/*struct.
|
||||
// The parameter `rules` can be type of []string/map[string]string. It supports sequence in error result
|
||||
// if `rules` is type of []string.
|
||||
// The optional parameter `messages` specifies the custom error messages for specified keys and rules.
|
||||
func CheckStruct(object interface{}, rules interface{}, messages ...CustomMsg) *Error {
|
||||
return defaultValidator.CheckStruct(object, rules, messages...)
|
||||
}
|
||||
|
@ -7,10 +7,10 @@
|
||||
package gvalid
|
||||
|
||||
// RuleFunc is the custom function for data validation.
|
||||
// The parameter <rule> specifies the validation rule string, like "required", "between:1,100", etc.
|
||||
// The parameter <value> specifies the value for this rule to validate.
|
||||
// The parameter <message> specifies the custom error message or configured i18n message for this rule.
|
||||
// The parameter <params> specifies all the parameters that needs. You can ignore parameter <params> if
|
||||
// The parameter `rule` specifies the validation rule string, like "required", "between:1,100", etc.
|
||||
// The parameter `value` specifies the value for this rule to validate.
|
||||
// The parameter `message` specifies the custom error message or configured i18n message for this rule.
|
||||
// The parameter `params` specifies all the parameters that needs. You can ignore parameter `params` if
|
||||
// you do not really need it in your custom validation rule.
|
||||
type RuleFunc func(rule string, value interface{}, message string, params map[string]interface{}) error
|
||||
|
||||
|
@ -21,12 +21,12 @@ import (
|
||||
// Check checks single value with specified rules.
|
||||
// It returns nil if successful validation.
|
||||
//
|
||||
// The parameter <value> can be any type of variable, which will be converted to string
|
||||
// The parameter `value` can be any type of variable, which will be converted to string
|
||||
// for validation.
|
||||
// The parameter <rules> can be one or more rules, multiple rules joined using char '|'.
|
||||
// The parameter <messages> specifies the custom error messages, which can be type of:
|
||||
// The parameter `rules` can be one or more rules, multiple rules joined using char '|'.
|
||||
// The parameter `messages` specifies the custom error messages, which can be type of:
|
||||
// string/map/struct/*struct.
|
||||
// The optional parameter <params> specifies the extra validation parameters for some rules
|
||||
// The optional parameter `params` specifies the extra validation parameters for some rules
|
||||
// like: required-*、same、different, etc.
|
||||
func (v *Validator) Check(value interface{}, rules string, messages interface{}, params ...interface{}) *Error {
|
||||
return v.doCheck("", value, rules, messages, params...)
|
||||
|
@ -13,9 +13,9 @@ import (
|
||||
|
||||
// CheckMap validates map and returns the error result. It returns nil if with successful validation.
|
||||
//
|
||||
// The parameter <rules> can be type of []string/map[string]string. It supports sequence in error result
|
||||
// if <rules> is type of []string.
|
||||
// The optional parameter <messages> specifies the custom error messages for specified keys and rules.
|
||||
// The parameter `rules` can be type of []string/map[string]string. It supports sequence in error result
|
||||
// if `rules` is type of []string.
|
||||
// The optional parameter `messages` specifies the custom error messages for specified keys and rules.
|
||||
func (v *Validator) CheckMap(params interface{}, rules interface{}, messages ...CustomMsg) *Error {
|
||||
// If there's no validation rules, it does nothing and returns quickly.
|
||||
if params == nil || rules == nil {
|
||||
|
@ -20,10 +20,10 @@ var (
|
||||
|
||||
// CheckStruct validates struct and returns the error result.
|
||||
//
|
||||
// The parameter <object> should be type of struct/*struct.
|
||||
// The parameter <rules> can be type of []string/map[string]string. It supports sequence in error result
|
||||
// if <rules> is type of []string.
|
||||
// The optional parameter <messages> specifies the custom error messages for specified keys and rules.
|
||||
// The parameter `object` should be type of struct/*struct.
|
||||
// The parameter `rules` can be type of []string/map[string]string. It supports sequence in error result
|
||||
// if `rules` is type of []string.
|
||||
// The optional parameter `messages` specifies the custom error messages for specified keys and rules.
|
||||
func (v *Validator) CheckStruct(object interface{}, rules interface{}, messages ...CustomMsg) *Error {
|
||||
var (
|
||||
errorMaps = make(ErrorMap) // Returned error.
|
||||
@ -56,7 +56,7 @@ func (v *Validator) CheckStruct(object interface{}, rules interface{}, messages
|
||||
params = make(map[string]interface{})
|
||||
checkRules = make(map[string]string)
|
||||
customMessage = make(CustomMsg)
|
||||
fieldAliases = make(map[string]string) // Alias names for <messages> overwriting struct tag names.
|
||||
fieldAliases = make(map[string]string) // Alias names for `messages` overwriting struct tag names.
|
||||
errorRules = make([]string, 0) // Sequence rules.
|
||||
)
|
||||
switch v := rules.(type) {
|
||||
@ -159,7 +159,7 @@ func (v *Validator) CheckStruct(object interface{}, rules interface{}, messages
|
||||
}
|
||||
|
||||
// Custom error messages,
|
||||
// which have the most priority than <rules> and struct tag.
|
||||
// which have the most priority than `rules` and struct tag.
|
||||
if len(messages) > 0 && len(messages[0]) > 0 {
|
||||
for k, v := range messages[0] {
|
||||
if a, ok := fieldAliases[k]; ok {
|
||||
|
@ -12,7 +12,7 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// checkLength checks <value> using length rules.
|
||||
// checkLength checks `value` using length rules.
|
||||
// The length is calculated using unicode string, which means one chinese character or letter
|
||||
// both has the length of 1.
|
||||
func (v *Validator) checkLength(value, ruleKey, ruleVal string, customMsgMap map[string]string) string {
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
package gvalid
|
||||
|
||||
// checkLuHn checks <value> with LUHN algorithm.
|
||||
// checkLuHn checks `value` with LUHN algorithm.
|
||||
// It's usually used for bank card number validation.
|
||||
func (v *Validator) checkLuHn(value string) bool {
|
||||
var (
|
||||
|
@ -11,7 +11,7 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// checkRange checks <value> using range rules.
|
||||
// checkRange checks `value` using range rules.
|
||||
func (v *Validator) checkRange(value, ruleKey, ruleVal string, customMsgMap map[string]string) string {
|
||||
msg := ""
|
||||
switch ruleKey {
|
||||
|
@ -12,7 +12,7 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// checkRequired checks <value> using required rules.
|
||||
// checkRequired checks `value` using required rules.
|
||||
// It also supports require checks for `value` of type: slice, map.
|
||||
func (v *Validator) checkRequired(value interface{}, ruleKey, rulePattern string, params map[string]string) bool {
|
||||
required := false
|
||||
|
Loading…
x
Reference in New Issue
Block a user