2020-07-26 17:09:05 +08:00
package mapping
import (
2022-10-20 20:11:19 +08:00
"encoding"
2025-01-22 21:25:35 +08:00
"encoding/base64"
2020-07-26 17:09:05 +08:00
"encoding/json"
"errors"
"fmt"
"reflect"
2022-11-12 13:58:35 +08:00
"strconv"
2020-07-26 17:09:05 +08:00
"strings"
"sync"
"time"
2022-01-04 15:51:32 +08:00
"github.com/zeromicro/go-zero/core/jsonx"
"github.com/zeromicro/go-zero/core/lang"
2022-11-11 23:17:09 +08:00
"github.com/zeromicro/go-zero/core/proc"
2022-01-04 15:51:32 +08:00
"github.com/zeromicro/go-zero/core/stringx"
2020-07-26 17:09:05 +08:00
)
const (
2024-12-23 00:56:20 +08:00
comma = ","
2023-10-15 10:06:00 +08:00
defaultKeyName = "key"
delimiter = '.'
ignoreKey = "-"
numberTypeString = "number"
2020-07-26 17:09:05 +08:00
)
var (
errTypeMismatch = errors . New ( "type mismatch" )
errValueNotSettable = errors . New ( "value is not settable" )
2020-09-28 15:19:30 +08:00
errValueNotStruct = errors . New ( "value type is not struct" )
2020-07-26 17:09:05 +08:00
keyUnmarshaler = NewUnmarshaler ( defaultKeyName )
durationType = reflect . TypeOf ( time . Duration ( 0 ) )
2022-10-06 23:57:56 +08:00
cacheKeys = make ( map [ string ] [ ] string )
2021-12-29 17:37:36 +08:00
cacheKeysLock sync . Mutex
2023-01-24 16:32:02 +08:00
defaultCache = make ( map [ string ] any )
2021-12-29 17:37:36 +08:00
defaultCacheLock sync . Mutex
2023-01-24 16:32:02 +08:00
emptyMap = map [ string ] any { }
2020-07-26 17:09:05 +08:00
emptyValue = reflect . ValueOf ( lang . Placeholder )
2024-12-23 00:56:20 +08:00
stringSliceType = reflect . TypeOf ( [ ] string { } )
2020-07-26 17:09:05 +08:00
)
type (
2024-03-08 22:35:17 +08:00
// Unmarshaler is used to unmarshal with the given tag key.
2020-07-26 17:09:05 +08:00
Unmarshaler struct {
key string
opts unmarshalOptions
}
2022-11-04 21:55:17 +08:00
// UnmarshalOption defines the method to customize an Unmarshaler.
2021-02-20 23:18:22 +08:00
UnmarshalOption func ( * unmarshalOptions )
2020-07-26 17:09:05 +08:00
unmarshalOptions struct {
2023-03-02 17:20:09 +08:00
fillDefault bool
2024-11-02 21:55:37 +08:00
fromArray bool
2021-08-10 17:38:03 +08:00
fromString bool
2023-08-14 22:22:22 +08:00
opaqueKeys bool
2021-08-10 17:38:03 +08:00
canonicalKey func ( key string ) string
2020-07-26 17:09:05 +08:00
}
)
2022-11-04 21:55:17 +08:00
// NewUnmarshaler returns an Unmarshaler.
2020-07-26 17:09:05 +08:00
func NewUnmarshaler ( key string , opts ... UnmarshalOption ) * Unmarshaler {
unmarshaler := Unmarshaler {
key : key ,
}
for _ , opt := range opts {
opt ( & unmarshaler . opts )
}
return & unmarshaler
}
2024-03-08 22:35:17 +08:00
// UnmarshalKey unmarshals m into v with the tag key.
2023-01-24 16:32:02 +08:00
func UnmarshalKey ( m map [ string ] any , v any ) error {
2020-07-26 17:09:05 +08:00
return keyUnmarshaler . Unmarshal ( m , v )
}
2021-02-20 23:18:22 +08:00
// Unmarshal unmarshals m into v.
2023-07-23 20:10:41 +08:00
func ( u * Unmarshaler ) Unmarshal ( i , v any ) error {
return u . unmarshal ( i , v , "" )
}
2021-02-20 23:18:22 +08:00
// UnmarshalValuer unmarshals m into v.
2023-01-24 16:32:02 +08:00
func ( u * Unmarshaler ) UnmarshalValuer ( m Valuer , v any ) error {
2023-07-23 20:10:41 +08:00
return u . unmarshalValuer ( simpleValuer { current : m } , v , "" )
}
2024-05-11 23:06:59 +08:00
func ( u * Unmarshaler ) fillMap ( fieldType reflect . Type , value reflect . Value ,
mapValue any , fullName string ) error {
2022-12-13 00:16:31 +08:00
if ! value . CanSet ( ) {
return errValueNotSettable
}
fieldKeyType := fieldType . Key ( )
fieldElemType := fieldType . Elem ( )
2023-07-23 20:10:41 +08:00
targetValue , err := u . generateMap ( fieldKeyType , fieldElemType , mapValue , fullName )
2022-12-13 00:16:31 +08:00
if err != nil {
2020-07-26 17:09:05 +08:00
return err
}
2022-12-13 00:16:31 +08:00
if ! targetValue . Type ( ) . AssignableTo ( value . Type ( ) ) {
return errTypeMismatch
2020-09-28 15:19:30 +08:00
}
2022-12-13 00:16:31 +08:00
value . Set ( targetValue )
return nil
}
2023-01-24 16:32:02 +08:00
func ( u * Unmarshaler ) fillMapFromString ( value reflect . Value , mapValue any ) error {
2022-12-13 00:16:31 +08:00
if ! value . CanSet ( ) {
return errValueNotSettable
}
switch v := mapValue . ( type ) {
case fmt . Stringer :
if err := jsonx . UnmarshalFromString ( v . String ( ) , value . Addr ( ) . Interface ( ) ) ; err != nil {
return err
}
case string :
if err := jsonx . UnmarshalFromString ( v , value . Addr ( ) . Interface ( ) ) ; err != nil {
2020-07-26 17:09:05 +08:00
return err
}
2022-12-13 00:16:31 +08:00
default :
return errUnsupportedType
2020-07-26 17:09:05 +08:00
}
return nil
}
2024-05-11 23:06:59 +08:00
func ( u * Unmarshaler ) fillSlice ( fieldType reflect . Type , value reflect . Value ,
mapValue any , fullName string ) error {
2022-12-13 00:16:31 +08:00
if ! value . CanSet ( ) {
return errValueNotSettable
2020-07-26 17:09:05 +08:00
}
2022-12-13 00:16:31 +08:00
refValue := reflect . ValueOf ( mapValue )
2023-05-26 00:21:47 +08:00
if refValue . Kind ( ) != reflect . Slice {
2023-07-23 20:40:03 +08:00
return newTypeMismatchErrorWithHint ( fullName , reflect . Slice . String ( ) , refValue . Type ( ) . String ( ) )
2023-05-26 00:21:47 +08:00
}
2022-12-13 00:16:31 +08:00
if refValue . IsNil ( ) {
return nil
2020-07-26 17:09:05 +08:00
}
2023-05-26 00:21:47 +08:00
baseType := fieldType . Elem ( )
dereffedBaseType := Deref ( baseType )
dereffedBaseKind := dereffedBaseType . Kind ( )
2022-12-13 00:16:31 +08:00
if refValue . Len ( ) == 0 {
2024-12-23 00:56:20 +08:00
value . Set ( reflect . MakeSlice ( reflect . SliceOf ( baseType ) , 0 , 0 ) )
2022-12-13 00:16:31 +08:00
return nil
2020-07-26 17:09:05 +08:00
}
2021-02-09 13:50:21 +08:00
2024-12-23 00:56:20 +08:00
if u . opts . fromArray {
refValue = makeStringSlice ( refValue )
}
2022-12-13 00:16:31 +08:00
var valid bool
2024-12-23 00:56:20 +08:00
conv := reflect . MakeSlice ( reflect . SliceOf ( baseType ) , refValue . Len ( ) , refValue . Cap ( ) )
2022-12-13 00:16:31 +08:00
for i := 0 ; i < refValue . Len ( ) ; i ++ {
ithValue := refValue . Index ( i ) . Interface ( )
if ithValue == nil {
continue
2020-07-26 17:09:05 +08:00
}
2023-07-23 20:40:03 +08:00
valid = true
2023-07-23 20:10:41 +08:00
sliceFullName := fmt . Sprintf ( "%s[%d]" , fullName , i )
2022-12-13 00:16:31 +08:00
switch dereffedBaseKind {
case reflect . Struct :
2024-12-23 00:56:20 +08:00
if err := u . fillStructElement ( baseType , conv . Index ( i ) , ithValue , sliceFullName ) ; err != nil {
2022-12-13 00:16:31 +08:00
return err
2020-07-26 17:09:05 +08:00
}
2022-12-13 00:16:31 +08:00
case reflect . Slice :
2023-07-23 20:10:41 +08:00
if err := u . fillSlice ( dereffedBaseType , conv . Index ( i ) , ithValue , sliceFullName ) ; err != nil {
2020-07-26 17:09:05 +08:00
return err
}
2022-12-13 00:16:31 +08:00
default :
2023-07-23 20:10:41 +08:00
if err := u . fillSliceValue ( conv , i , dereffedBaseKind , ithValue , sliceFullName ) ; err != nil {
2022-12-13 00:16:31 +08:00
return err
2020-07-26 17:09:05 +08:00
}
}
}
2022-12-13 00:16:31 +08:00
if valid {
value . Set ( conv )
2020-07-26 17:09:05 +08:00
}
return nil
}
2022-12-13 00:16:31 +08:00
func ( u * Unmarshaler ) fillSliceFromString ( fieldType reflect . Type , value reflect . Value ,
2024-05-11 23:06:59 +08:00
mapValue any , fullName string ) error {
2023-01-24 16:32:02 +08:00
var slice [ ] any
2022-12-13 00:16:31 +08:00
switch v := mapValue . ( type ) {
case fmt . Stringer :
if err := jsonx . UnmarshalFromString ( v . String ( ) , & slice ) ; err != nil {
2024-02-23 22:00:58 +08:00
return fmt . Errorf ( "fullName: `%s`, error: `%w`" , fullName , err )
2020-07-26 17:09:05 +08:00
}
2022-12-13 00:16:31 +08:00
case string :
if err := jsonx . UnmarshalFromString ( v , & slice ) ; err != nil {
2024-02-23 22:00:58 +08:00
return fmt . Errorf ( "fullName: `%s`, error: `%w`" , fullName , err )
2022-11-08 15:27:48 +08:00
}
2020-07-26 17:09:05 +08:00
default :
2022-12-13 00:16:31 +08:00
return errUnsupportedType
2020-07-26 17:09:05 +08:00
}
2024-12-23 00:56:20 +08:00
baseFieldType := fieldType . Elem ( )
2022-12-13 00:16:31 +08:00
baseFieldKind := baseFieldType . Kind ( )
conv := reflect . MakeSlice ( reflect . SliceOf ( baseFieldType ) , len ( slice ) , cap ( slice ) )
2020-07-26 17:09:05 +08:00
2022-12-13 00:16:31 +08:00
for i := 0 ; i < len ( slice ) ; i ++ {
2023-07-23 20:10:41 +08:00
if err := u . fillSliceValue ( conv , i , baseFieldKind , slice [ i ] , fullName ) ; err != nil {
2022-12-13 00:16:31 +08:00
return err
2020-07-26 17:09:05 +08:00
}
}
2022-12-13 00:16:31 +08:00
value . Set ( conv )
return nil
2020-07-26 17:09:05 +08:00
}
2022-12-13 00:16:31 +08:00
func ( u * Unmarshaler ) fillSliceValue ( slice reflect . Value , index int ,
2024-05-11 23:06:59 +08:00
baseKind reflect . Kind , value any , fullName string ) error {
2024-01-13 21:48:43 +08:00
if value == nil {
2024-01-13 22:11:19 +08:00
return errNilSliceElement
2024-01-13 21:48:43 +08:00
}
2024-01-13 22:11:19 +08:00
2022-12-13 00:16:31 +08:00
ithVal := slice . Index ( index )
2024-12-23 00:56:20 +08:00
ithValType := ithVal . Type ( )
2022-12-13 00:16:31 +08:00
switch v := value . ( type ) {
case fmt . Stringer :
2023-01-12 15:56:51 +08:00
return setValueFromString ( baseKind , ithVal , v . String ( ) )
2022-12-13 00:16:31 +08:00
case string :
2023-01-12 15:56:51 +08:00
return setValueFromString ( baseKind , ithVal , v )
2023-01-24 16:32:02 +08:00
case map [ string ] any :
2024-12-23 00:56:20 +08:00
// deref to handle both pointer and non-pointer types.
switch Deref ( ithValType ) . Kind ( ) {
case reflect . Struct :
return u . fillStructElement ( ithValType , ithVal , v , fullName )
case reflect . Map :
return u . fillMap ( ithValType , ithVal , value , fullName )
default :
return errTypeMismatch
}
2022-12-13 00:16:31 +08:00
default :
// don't need to consider the difference between int, int8, int16, int32, int64,
// uint, uint8, uint16, uint32, uint64, because they're handled as json.Number.
if ithVal . Kind ( ) == reflect . Ptr {
2024-12-23 00:56:20 +08:00
baseType := Deref ( ithValType )
2022-12-13 00:16:31 +08:00
if ! reflect . TypeOf ( value ) . AssignableTo ( baseType ) {
return errTypeMismatch
}
2020-07-26 17:09:05 +08:00
2022-12-13 00:16:31 +08:00
target := reflect . New ( baseType ) . Elem ( )
target . Set ( reflect . ValueOf ( value ) )
2024-12-23 00:56:20 +08:00
SetValue ( ithValType , ithVal , target )
2022-12-13 00:16:31 +08:00
return nil
2020-07-26 17:09:05 +08:00
}
2024-12-23 00:56:20 +08:00
if ! reflect . TypeOf ( value ) . AssignableTo ( ithValType ) {
2022-12-13 00:16:31 +08:00
return errTypeMismatch
2020-07-26 17:09:05 +08:00
}
2022-12-13 00:16:31 +08:00
ithVal . Set ( reflect . ValueOf ( value ) )
return nil
}
}
2022-04-13 19:06:00 +08:00
2022-12-13 00:16:31 +08:00
func ( u * Unmarshaler ) fillSliceWithDefault ( derefedType reflect . Type , value reflect . Value ,
2024-05-11 23:06:59 +08:00
defaultValue , fullName string ) error {
2022-12-13 00:16:31 +08:00
baseFieldType := Deref ( derefedType . Elem ( ) )
baseFieldKind := baseFieldType . Kind ( )
defaultCacheLock . Lock ( )
slice , ok := defaultCache [ defaultValue ]
defaultCacheLock . Unlock ( )
if ! ok {
if baseFieldKind == reflect . String {
slice = parseGroupedSegments ( defaultValue )
} else if err := jsonx . UnmarshalFromString ( defaultValue , & slice ) ; err != nil {
2020-07-26 17:09:05 +08:00
return err
}
2022-12-13 00:16:31 +08:00
defaultCacheLock . Lock ( )
defaultCache [ defaultValue ] = slice
defaultCacheLock . Unlock ( )
2020-07-26 17:09:05 +08:00
}
2023-07-23 20:10:41 +08:00
return u . fillSlice ( derefedType , value , slice , fullName )
2020-07-26 17:09:05 +08:00
}
2024-12-23 00:56:20 +08:00
func ( u * Unmarshaler ) fillStructElement ( baseType reflect . Type , target reflect . Value ,
value any , fullName string ) error {
val , ok := value . ( map [ string ] any )
if ! ok {
return errTypeMismatch
}
// use Deref(baseType) to get the base type in case the type is a pointer type.
ptr := reflect . New ( Deref ( baseType ) )
if err := u . unmarshal ( val , ptr . Interface ( ) , fullName ) ; err != nil {
return err
}
SetValue ( baseType , target , ptr . Elem ( ) )
return nil
}
2024-05-12 14:37:36 +08:00
func ( u * Unmarshaler ) fillUnmarshalerStruct ( fieldType reflect . Type ,
value reflect . Value , targetValue string ) error {
if ! value . CanSet ( ) {
return errValueNotSettable
}
baseType := Deref ( fieldType )
target := reflect . New ( baseType )
switch u . key {
case jsonTagKey :
unmarshaler , ok := target . Interface ( ) . ( json . Unmarshaler )
if ! ok {
return errUnsupportedType
}
if err := unmarshaler . UnmarshalJSON ( [ ] byte ( targetValue ) ) ; err != nil {
return err
}
default :
return errUnsupportedType
}
value . Set ( target )
return nil
}
2024-05-11 23:06:59 +08:00
func ( u * Unmarshaler ) generateMap ( keyType , elemType reflect . Type , mapValue any ,
fullName string ) ( reflect . Value , error ) {
2022-12-13 00:16:31 +08:00
mapType := reflect . MapOf ( keyType , elemType )
valueType := reflect . TypeOf ( mapValue )
if mapType == valueType {
return reflect . ValueOf ( mapValue ) , nil
2020-07-26 17:09:05 +08:00
}
2023-03-11 07:53:57 +08:00
if keyType != valueType . Key ( ) {
return emptyValue , errTypeMismatch
}
2022-12-13 00:16:31 +08:00
refValue := reflect . ValueOf ( mapValue )
targetValue := reflect . MakeMapWithSize ( mapType , refValue . Len ( ) )
dereffedElemType := Deref ( elemType )
dereffedElemKind := dereffedElemType . Kind ( )
2020-07-26 17:09:05 +08:00
2022-12-13 00:16:31 +08:00
for _ , key := range refValue . MapKeys ( ) {
keythValue := refValue . MapIndex ( key )
keythData := keythValue . Interface ( )
2023-07-23 20:10:41 +08:00
mapFullName := fmt . Sprintf ( "%s[%s]" , fullName , key . String ( ) )
2022-12-13 00:16:31 +08:00
switch dereffedElemKind {
case reflect . Slice :
target := reflect . New ( dereffedElemType )
2023-07-23 20:10:41 +08:00
if err := u . fillSlice ( elemType , target . Elem ( ) , keythData , mapFullName ) ; err != nil {
2022-12-13 00:16:31 +08:00
return emptyValue , err
}
2022-10-20 20:11:19 +08:00
2022-12-13 00:16:31 +08:00
targetValue . SetMapIndex ( key , target . Elem ( ) )
case reflect . Struct :
2023-01-24 16:32:02 +08:00
keythMap , ok := keythData . ( map [ string ] any )
2022-12-13 00:16:31 +08:00
if ! ok {
return emptyValue , errTypeMismatch
}
2022-10-20 20:11:19 +08:00
2022-12-13 00:16:31 +08:00
target := reflect . New ( dereffedElemType )
2023-07-23 20:10:41 +08:00
if err := u . unmarshal ( keythMap , target . Interface ( ) , mapFullName ) ; err != nil {
2022-12-13 00:16:31 +08:00
return emptyValue , err
}
2022-11-18 19:46:23 +08:00
2023-01-12 15:56:51 +08:00
SetMapIndexValue ( elemType , targetValue , key , target . Elem ( ) )
2022-12-13 00:16:31 +08:00
case reflect . Map :
2023-01-24 16:32:02 +08:00
keythMap , ok := keythData . ( map [ string ] any )
2022-12-13 00:16:31 +08:00
if ! ok {
return emptyValue , errTypeMismatch
}
2022-11-12 13:58:35 +08:00
2023-07-23 20:10:41 +08:00
innerValue , err := u . generateMap ( elemType . Key ( ) , elemType . Elem ( ) , keythMap , mapFullName )
2022-12-13 00:16:31 +08:00
if err != nil {
return emptyValue , err
}
2022-11-11 23:17:09 +08:00
2022-12-13 00:16:31 +08:00
targetValue . SetMapIndex ( key , innerValue )
default :
switch v := keythData . ( type ) {
case bool :
if dereffedElemKind != reflect . Bool {
return emptyValue , errTypeMismatch
}
2022-11-11 23:17:09 +08:00
2022-12-13 00:16:31 +08:00
targetValue . SetMapIndex ( key , reflect . ValueOf ( v ) )
case string :
if dereffedElemKind != reflect . String {
return emptyValue , errTypeMismatch
}
2021-08-10 17:59:33 +08:00
2023-05-26 22:30:03 +08:00
val := reflect . ValueOf ( v )
if ! val . Type ( ) . AssignableTo ( dereffedElemType ) {
return emptyValue , errTypeMismatch
}
targetValue . SetMapIndex ( key , val )
2022-12-13 00:16:31 +08:00
case json . Number :
target := reflect . New ( dereffedElemType )
2023-01-12 15:56:51 +08:00
if err := setValueFromString ( dereffedElemKind , target . Elem ( ) , v . String ( ) ) ; err != nil {
2022-12-13 00:16:31 +08:00
return emptyValue , err
}
targetValue . SetMapIndex ( key , target . Elem ( ) )
default :
if dereffedElemKind != keythValue . Kind ( ) {
return emptyValue , errTypeMismatch
}
targetValue . SetMapIndex ( key , keythValue )
}
2022-11-11 23:17:09 +08:00
}
}
2022-12-13 00:16:31 +08:00
return targetValue , nil
}
2024-05-12 14:37:36 +08:00
func ( u * Unmarshaler ) implementsUnmarshaler ( t reflect . Type ) bool {
switch u . key {
case jsonTagKey :
return t . Implements ( reflect . TypeOf ( ( * json . Unmarshaler ) ( nil ) ) . Elem ( ) )
default :
return false
}
}
2022-12-13 00:16:31 +08:00
func ( u * Unmarshaler ) parseOptionsWithContext ( field reflect . StructField , m Valuer , fullName string ) (
2024-05-11 23:06:59 +08:00
string , * fieldOptionsWithContext , error ) {
2022-12-13 00:16:31 +08:00
key , options , err := parseKeyAndOptions ( u . key , field )
if err != nil {
return "" , nil , err
} else if options == nil {
return key , nil , nil
2021-08-10 17:38:03 +08:00
}
2022-11-08 15:27:48 +08:00
2023-01-20 23:57:49 +08:00
if u . opts . canonicalKey != nil {
key = u . opts . canonicalKey ( key )
if len ( options . OptionalDep ) > 0 {
// need to create a new fieldOption, because the original one is shared through cache.
options = & fieldOptions {
fieldOptionsWithContext : fieldOptionsWithContext {
Inherit : options . Inherit ,
FromString : options . FromString ,
Optional : options . Optional ,
Options : options . Options ,
Default : options . Default ,
EnvVar : options . EnvVar ,
Range : options . Range ,
} ,
OptionalDep : u . opts . canonicalKey ( options . OptionalDep ) ,
}
}
}
2024-02-28 00:23:47 +08:00
if u . opts . fillDefault {
return key , & options . fieldOptionsWithContext , nil
}
2022-12-13 00:16:31 +08:00
optsWithContext , err := options . toOptionsWithContext ( key , m , fullName )
if err != nil {
return "" , nil , err
2020-07-26 17:09:05 +08:00
}
2021-02-09 13:50:21 +08:00
2022-12-13 00:16:31 +08:00
return key , optsWithContext , nil
2020-07-26 17:09:05 +08:00
}
2022-12-13 00:16:31 +08:00
func ( u * Unmarshaler ) processAnonymousField ( field reflect . StructField , value reflect . Value ,
2024-05-11 23:06:59 +08:00
m valuerWithParent , fullName string ) error {
2022-12-13 00:16:31 +08:00
key , options , err := u . parseOptionsWithContext ( field , m , fullName )
if err != nil {
return err
2020-07-26 17:09:05 +08:00
}
2023-08-27 16:04:38 +08:00
if key == ignoreKey {
return nil
}
2022-12-13 00:16:31 +08:00
if options . optional ( ) {
2022-12-24 21:26:33 +08:00
return u . processAnonymousFieldOptional ( field , value , key , m , fullName )
2022-10-20 20:11:19 +08:00
}
2022-12-24 21:26:33 +08:00
return u . processAnonymousFieldRequired ( field , value , m , fullName )
2022-12-13 00:16:31 +08:00
}
2020-07-26 17:09:05 +08:00
2022-12-24 21:26:33 +08:00
func ( u * Unmarshaler ) processAnonymousFieldOptional ( field reflect . StructField , value reflect . Value ,
2024-05-11 23:06:59 +08:00
key string , m valuerWithParent , fullName string ) error {
2022-12-24 21:26:33 +08:00
derefedFieldType := Deref ( field . Type )
switch derefedFieldType . Kind ( ) {
case reflect . Struct :
return u . processAnonymousStructFieldOptional ( field . Type , value , key , m , fullName )
default :
return u . processNamedField ( field , value , m , fullName )
}
}
func ( u * Unmarshaler ) processAnonymousFieldRequired ( field reflect . StructField , value reflect . Value ,
2024-05-11 23:06:59 +08:00
m valuerWithParent , fullName string ) error {
2022-12-24 21:26:33 +08:00
fieldType := field . Type
maybeNewValue ( fieldType , value )
derefedFieldType := Deref ( fieldType )
indirectValue := reflect . Indirect ( value )
switch derefedFieldType . Kind ( ) {
case reflect . Struct :
for i := 0 ; i < derefedFieldType . NumField ( ) ; i ++ {
if err := u . processField ( derefedFieldType . Field ( i ) , indirectValue . Field ( i ) ,
m , fullName ) ; err != nil {
return err
}
}
default :
if err := u . processNamedField ( field , indirectValue , m , fullName ) ; err != nil {
return err
}
}
return nil
}
func ( u * Unmarshaler ) processAnonymousStructFieldOptional ( fieldType reflect . Type ,
2024-05-11 23:06:59 +08:00
value reflect . Value , key string , m valuerWithParent , fullName string ) error {
2022-12-13 00:16:31 +08:00
var filled bool
var required int
var requiredFilled int
var indirectValue reflect . Value
derefedFieldType := Deref ( fieldType )
2020-07-26 17:09:05 +08:00
2022-12-13 00:16:31 +08:00
for i := 0 ; i < derefedFieldType . NumField ( ) ; i ++ {
subField := derefedFieldType . Field ( i )
fieldKey , fieldOpts , err := u . parseOptionsWithContext ( subField , m , fullName )
if err != nil {
return err
2020-07-26 17:09:05 +08:00
}
2023-08-14 22:22:22 +08:00
_ , hasValue := getValue ( m , fieldKey , u . opts . opaqueKeys )
2022-12-13 00:16:31 +08:00
if hasValue {
if ! filled {
filled = true
maybeNewValue ( fieldType , value )
indirectValue = reflect . Indirect ( value )
}
if err = u . processField ( subField , indirectValue . Field ( i ) , m , fullName ) ; err != nil {
return err
}
2020-07-26 17:09:05 +08:00
}
2022-12-13 00:16:31 +08:00
if ! fieldOpts . optional ( ) {
required ++
if hasValue {
requiredFilled ++
}
2020-07-26 17:09:05 +08:00
}
2022-12-13 00:16:31 +08:00
}
2021-12-29 17:37:36 +08:00
2022-12-13 00:16:31 +08:00
if filled && required != requiredFilled {
2023-04-24 12:11:12 +08:00
return fmt . Errorf ( "%q is not fully set" , key )
2020-07-26 17:09:05 +08:00
}
2022-12-13 00:16:31 +08:00
return nil
}
2022-11-08 15:27:48 +08:00
2022-12-13 00:16:31 +08:00
func ( u * Unmarshaler ) processField ( field reflect . StructField , value reflect . Value ,
2024-05-11 23:06:59 +08:00
m valuerWithParent , fullName string ) error {
2022-12-13 00:16:31 +08:00
if usingDifferentKeys ( u . key , field ) {
return nil
2020-07-26 17:09:05 +08:00
}
2022-12-13 00:16:31 +08:00
if field . Anonymous {
return u . processAnonymousField ( field , value , m , fullName )
2020-07-26 17:09:05 +08:00
}
2022-12-13 00:16:31 +08:00
return u . processNamedField ( field , value , m , fullName )
2020-07-26 17:09:05 +08:00
}
2022-12-13 00:16:31 +08:00
func ( u * Unmarshaler ) processFieldNotFromString ( fieldType reflect . Type , value reflect . Value ,
2024-05-11 23:06:59 +08:00
vp valueWithParent , opts * fieldOptionsWithContext , fullName string ) error {
2022-12-13 00:16:31 +08:00
derefedFieldType := Deref ( fieldType )
typeKind := derefedFieldType . Kind ( )
mapValue := vp . value
2023-05-24 23:58:45 +08:00
valueKind := reflect . TypeOf ( mapValue ) . Kind ( )
2022-09-30 14:57:40 +08:00
2022-12-13 00:16:31 +08:00
switch {
case valueKind == reflect . Map && typeKind == reflect . Struct :
2023-01-24 16:32:02 +08:00
mv , ok := mapValue . ( map [ string ] any )
2022-12-13 00:16:31 +08:00
if ! ok {
return errTypeMismatch
2022-09-30 14:57:40 +08:00
}
2022-12-13 00:16:31 +08:00
return u . processFieldStruct ( fieldType , value , & simpleValuer {
current : mapValuer ( mv ) ,
parent : vp . parent ,
} , fullName )
2023-05-24 23:58:45 +08:00
case typeKind == reflect . Slice && valueKind == reflect . Slice :
2023-07-23 20:10:41 +08:00
return u . fillSlice ( fieldType , value , mapValue , fullName )
2022-12-13 00:16:31 +08:00
case valueKind == reflect . Map && typeKind == reflect . Map :
2023-07-23 20:10:41 +08:00
return u . fillMap ( fieldType , value , mapValue , fullName )
2022-12-13 00:16:31 +08:00
case valueKind == reflect . String && typeKind == reflect . Map :
return u . fillMapFromString ( value , mapValue )
case valueKind == reflect . String && typeKind == reflect . Slice :
2025-01-22 21:25:35 +08:00
// try to find out if it's a byte slice, golang use []byte Marshal to base64 but there only SliceOf uint8/bytes can convert to []byte
// more details https://pkg.go.dev/encoding/json#Marshal
//> Array and slice values encode as JSON arrays, except that []byte encodes as a base64-encoded string, and a nil slice encodes as the null JSON value.
//and also u can find this https://stackoverflow.com/questions/34089750/marshal-byte-to-json-giving-a-strange-string
if fieldType . Elem ( ) . Kind ( ) == reflect . Uint8 {
strVal := mapValue . ( string )
decodedBytes , err := base64 . StdEncoding . DecodeString ( strVal )
// if err !=nil do next
if err == nil {
value . Set ( reflect . ValueOf ( decodedBytes ) )
return nil
}
}
2023-07-23 20:10:41 +08:00
return u . fillSliceFromString ( fieldType , value , mapValue , fullName )
2022-12-13 00:16:31 +08:00
case valueKind == reflect . String && derefedFieldType == durationType :
2023-01-12 15:56:51 +08:00
return fillDurationValue ( fieldType , value , mapValue . ( string ) )
2024-05-12 14:37:36 +08:00
case valueKind == reflect . String && typeKind == reflect . Struct && u . implementsUnmarshaler ( fieldType ) :
return u . fillUnmarshalerStruct ( fieldType , value , mapValue . ( string ) )
2022-09-30 14:57:40 +08:00
default :
2022-12-13 00:16:31 +08:00
return u . processFieldPrimitive ( fieldType , value , mapValue , opts , fullName )
2022-09-30 14:57:40 +08:00
}
2022-12-13 00:16:31 +08:00
}
2022-09-30 14:57:40 +08:00
2022-12-13 00:16:31 +08:00
func ( u * Unmarshaler ) processFieldPrimitive ( fieldType reflect . Type , value reflect . Value ,
2024-05-11 23:06:59 +08:00
mapValue any , opts * fieldOptionsWithContext , fullName string ) error {
2022-12-13 00:16:31 +08:00
typeKind := Deref ( fieldType ) . Kind ( )
valueKind := reflect . TypeOf ( mapValue ) . Kind ( )
2023-05-24 23:58:45 +08:00
switch v := mapValue . ( type ) {
case json . Number :
return u . processFieldPrimitiveWithJSONNumber ( fieldType , value , v , opts , fullName )
2022-12-13 00:16:31 +08:00
default :
2023-05-24 23:58:45 +08:00
if typeKind == valueKind {
if err := validateValueInOptions ( mapValue , opts . options ( ) ) ; err != nil {
return err
2022-12-13 00:16:31 +08:00
}
2023-05-24 23:58:45 +08:00
return fillWithSameType ( fieldType , value , mapValue , opts )
2022-12-13 00:16:31 +08:00
}
}
return newTypeMismatchError ( fullName )
2022-09-30 14:57:40 +08:00
}
2022-12-13 00:16:31 +08:00
func ( u * Unmarshaler ) processFieldPrimitiveWithJSONNumber ( fieldType reflect . Type , value reflect . Value ,
2024-05-11 23:06:59 +08:00
v json . Number , opts * fieldOptionsWithContext , fullName string ) error {
2023-01-12 15:56:51 +08:00
baseType := Deref ( fieldType )
typeKind := baseType . Kind ( )
2022-12-13 00:16:31 +08:00
if err := validateJsonNumberRange ( v , opts ) ; err != nil {
return err
2020-07-26 17:09:05 +08:00
}
2022-12-13 00:16:31 +08:00
if err := validateValueInOptions ( v , opts . options ( ) ) ; err != nil {
return err
2022-03-24 22:10:15 +08:00
}
2020-07-26 17:09:05 +08:00
2023-01-12 15:56:51 +08:00
target := reflect . New ( Deref ( fieldType ) ) . Elem ( )
2022-03-24 21:41:38 +08:00
2022-12-13 00:16:31 +08:00
switch typeKind {
2023-09-21 22:22:33 +08:00
case reflect . Int , reflect . Int8 , reflect . Int16 , reflect . Int32 , reflect . Int64 ,
reflect . Uint , reflect . Uint8 , reflect . Uint16 , reflect . Uint32 , reflect . Uint64 :
if err := setValueFromString ( typeKind , target , v . String ( ) ) ; err != nil {
2022-12-13 00:16:31 +08:00
return err
}
2023-09-26 21:46:34 +08:00
case reflect . Float32 :
fValue , err := v . Float64 ( )
if err != nil {
return err
}
2024-03-08 22:35:17 +08:00
// if the value is a pointer, we need to check overflow with the pointer's value.
2024-01-14 09:37:01 +08:00
derefedValue := value
for derefedValue . Type ( ) . Kind ( ) == reflect . Ptr {
derefedValue = derefedValue . Elem ( )
2024-01-13 23:48:50 +08:00
}
2024-01-14 09:37:01 +08:00
if derefedValue . CanFloat ( ) && derefedValue . OverflowFloat ( fValue ) {
2023-10-09 21:00:09 +08:00
return fmt . Errorf ( "parsing %q as float32: value out of range" , v . String ( ) )
2023-09-26 21:46:34 +08:00
}
target . SetFloat ( fValue )
case reflect . Float64 :
2022-12-13 00:16:31 +08:00
fValue , err := v . Float64 ( )
if err != nil {
return err
}
2023-01-12 15:56:51 +08:00
target . SetFloat ( fValue )
2022-12-13 00:16:31 +08:00
default :
2023-10-15 10:06:00 +08:00
return newTypeMismatchErrorWithHint ( fullName , typeKind . String ( ) , numberTypeString )
2020-07-26 17:09:05 +08:00
}
2023-01-12 15:56:51 +08:00
SetValue ( fieldType , value , target )
2020-07-26 17:09:05 +08:00
return nil
}
2022-12-13 00:16:31 +08:00
func ( u * Unmarshaler ) processFieldStruct ( fieldType reflect . Type , value reflect . Value ,
2024-05-11 23:06:59 +08:00
m valuerWithParent , fullName string ) error {
2022-12-13 00:16:31 +08:00
if fieldType . Kind ( ) == reflect . Ptr {
baseType := Deref ( fieldType )
target := reflect . New ( baseType ) . Elem ( )
if err := u . unmarshalWithFullName ( m , target . Addr ( ) . Interface ( ) , fullName ) ; err != nil {
2022-06-03 00:27:48 +08:00
return err
}
2022-12-13 00:16:31 +08:00
2023-01-12 15:56:51 +08:00
SetValue ( fieldType , value , target )
2022-12-13 00:16:31 +08:00
} else if err := u . unmarshalWithFullName ( m , value . Addr ( ) . Interface ( ) , fullName ) ; err != nil {
return err
2020-07-26 17:09:05 +08:00
}
2022-12-13 00:16:31 +08:00
return nil
}
2020-07-26 17:09:05 +08:00
2022-12-13 00:16:31 +08:00
func ( u * Unmarshaler ) processFieldTextUnmarshaler ( fieldType reflect . Type , value reflect . Value ,
2024-05-11 23:06:59 +08:00
mapValue any ) ( bool , error ) {
2022-12-13 00:16:31 +08:00
var tval encoding . TextUnmarshaler
var ok bool
if fieldType . Kind ( ) == reflect . Ptr {
2023-01-12 15:56:51 +08:00
if value . Elem ( ) . Kind ( ) == reflect . Ptr {
target := reflect . New ( Deref ( fieldType ) )
SetValue ( fieldType . Elem ( ) , value , target )
tval , ok = target . Interface ( ) . ( encoding . TextUnmarshaler )
} else {
tval , ok = value . Interface ( ) . ( encoding . TextUnmarshaler )
}
2022-12-13 00:16:31 +08:00
} else {
tval , ok = value . Addr ( ) . Interface ( ) . ( encoding . TextUnmarshaler )
}
if ok {
switch mv := mapValue . ( type ) {
case string :
return true , tval . UnmarshalText ( [ ] byte ( mv ) )
case [ ] byte :
return true , tval . UnmarshalText ( mv )
2020-07-26 17:09:05 +08:00
}
}
2025-01-22 21:35:32 +08:00
//[]byte
if fieldType . Kind ( ) == reflect . Slice && fieldType . Elem ( ) . Kind ( ) == reflect . Uint8 {
b , err := base64 . StdEncoding . DecodeString ( mapValue . ( string ) )
if err != nil {
return false , err
}
value . SetBytes ( b )
return true , nil
}
2022-12-13 00:16:31 +08:00
return false , nil
2020-07-26 17:09:05 +08:00
}
2022-12-13 00:16:31 +08:00
func ( u * Unmarshaler ) processFieldWithEnvValue ( fieldType reflect . Type , value reflect . Value ,
2024-05-11 23:06:59 +08:00
envVal string , opts * fieldOptionsWithContext , fullName string ) error {
2022-12-13 00:16:31 +08:00
if err := validateValueInOptions ( envVal , opts . options ( ) ) ; err != nil {
return err
}
2021-06-23 14:57:37 +08:00
2022-12-13 00:16:31 +08:00
fieldKind := fieldType . Kind ( )
switch fieldKind {
case reflect . Bool :
val , err := strconv . ParseBool ( envVal )
if err != nil {
return fmt . Errorf ( "unmarshal field %q with environment variable, %w" , fullName , err )
2021-08-11 11:38:55 +08:00
}
2021-06-23 10:58:01 +08:00
2022-12-13 00:16:31 +08:00
value . SetBool ( val )
return nil
case durationType . Kind ( ) :
2023-01-12 15:56:51 +08:00
if err := fillDurationValue ( fieldType , value , envVal ) ; err != nil {
2022-12-13 00:16:31 +08:00
return fmt . Errorf ( "unmarshal field %q with environment variable, %w" , fullName , err )
2021-06-23 10:58:01 +08:00
}
2021-08-11 11:38:55 +08:00
return nil
2022-12-13 00:16:31 +08:00
case reflect . String :
value . SetString ( envVal )
return nil
default :
return u . processFieldPrimitiveWithJSONNumber ( fieldType , value , json . Number ( envVal ) , opts , fullName )
2020-07-26 17:09:05 +08:00
}
}
2022-12-13 00:16:31 +08:00
func ( u * Unmarshaler ) processNamedField ( field reflect . StructField , value reflect . Value ,
2024-05-11 23:06:59 +08:00
m valuerWithParent , fullName string ) error {
2023-03-23 23:45:57 +08:00
if ! field . IsExported ( ) {
return nil
}
2022-12-13 00:16:31 +08:00
key , opts , err := u . parseOptionsWithContext ( field , m , fullName )
if err != nil {
return err
}
2023-08-27 16:04:38 +08:00
if key == ignoreKey {
return nil
}
2022-12-13 00:16:31 +08:00
fullName = join ( fullName , key )
if opts != nil && len ( opts . EnvVar ) > 0 {
envVal := proc . Env ( opts . EnvVar )
if len ( envVal ) > 0 {
return u . processFieldWithEnvValue ( field . Type , value , envVal , opts , fullName )
2021-12-29 17:37:36 +08:00
}
2022-12-13 00:16:31 +08:00
}
2021-12-29 17:37:36 +08:00
2022-12-13 00:16:31 +08:00
canonicalKey := key
if u . opts . canonicalKey != nil {
canonicalKey = u . opts . canonicalKey ( key )
2021-12-29 17:37:36 +08:00
}
2022-12-13 00:16:31 +08:00
valuer := createValuer ( m , opts )
2023-08-14 22:22:22 +08:00
mapValue , hasValue := getValue ( valuer , canonicalKey , u . opts . opaqueKeys )
2023-03-02 21:47:07 +08:00
2023-03-02 21:54:09 +08:00
// When fillDefault is used, m is a null value, hasValue must be false, all priority judgments fillDefault.
2023-03-02 21:47:07 +08:00
if u . opts . fillDefault {
if ! value . IsZero ( ) {
2023-04-24 12:11:12 +08:00
return fmt . Errorf ( "set the default value, %q must be zero" , fullName )
2023-03-02 21:47:07 +08:00
}
return u . processNamedFieldWithoutValue ( field . Type , value , opts , fullName )
} else if ! hasValue {
2022-12-13 00:16:31 +08:00
return u . processNamedFieldWithoutValue ( field . Type , value , opts , fullName )
}
2024-11-02 21:55:37 +08:00
if u . opts . fromArray {
fieldKind := field . Type . Kind ( )
if fieldKind != reflect . Slice && fieldKind != reflect . Array {
valueKind := reflect . TypeOf ( mapValue ) . Kind ( )
if valueKind == reflect . Slice || valueKind == reflect . Array {
val := reflect . ValueOf ( mapValue )
if val . Len ( ) > 0 {
mapValue = val . Index ( 0 ) . Interface ( )
}
}
}
}
2022-12-13 00:16:31 +08:00
return u . processNamedFieldWithValue ( field . Type , value , valueWithParent {
value : mapValue ,
parent : valuer ,
} , key , opts , fullName )
2021-12-29 17:37:36 +08:00
}
2022-12-13 00:16:31 +08:00
func ( u * Unmarshaler ) processNamedFieldWithValue ( fieldType reflect . Type , value reflect . Value ,
2024-05-11 23:06:59 +08:00
vp valueWithParent , key string , opts * fieldOptionsWithContext , fullName string ) error {
2022-12-13 00:16:31 +08:00
mapValue := vp . value
if mapValue == nil {
if opts . optional ( ) {
return nil
}
2020-07-26 17:09:05 +08:00
2023-04-24 12:11:12 +08:00
return fmt . Errorf ( "field %q mustn't be nil" , key )
2022-12-13 00:16:31 +08:00
}
2020-07-26 17:09:05 +08:00
2022-12-13 00:16:31 +08:00
if ! value . CanSet ( ) {
2023-04-24 12:11:12 +08:00
return fmt . Errorf ( "field %q is not settable" , key )
2022-12-13 00:16:31 +08:00
}
2020-07-26 17:09:05 +08:00
2022-12-13 00:16:31 +08:00
maybeNewValue ( fieldType , value )
2020-07-26 17:09:05 +08:00
2022-12-13 00:16:31 +08:00
if yes , err := u . processFieldTextUnmarshaler ( fieldType , value , mapValue ) ; yes {
return err
}
2020-07-26 17:09:05 +08:00
2022-12-13 00:16:31 +08:00
fieldKind := Deref ( fieldType ) . Kind ( )
switch fieldKind {
case reflect . Array , reflect . Map , reflect . Slice , reflect . Struct :
return u . processFieldNotFromString ( fieldType , value , vp , opts , fullName )
default :
if u . opts . fromString || opts . fromString ( ) {
2023-01-11 00:45:11 +08:00
return u . processNamedFieldWithValueFromString ( fieldType , value , mapValue ,
key , opts , fullName )
}
2020-07-26 17:09:05 +08:00
2023-01-11 00:45:11 +08:00
return u . processFieldNotFromString ( fieldType , value , vp , opts , fullName )
}
}
func ( u * Unmarshaler ) processNamedFieldWithValueFromString ( fieldType reflect . Type , value reflect . Value ,
2024-05-11 23:06:59 +08:00
mapValue any , key string , opts * fieldOptionsWithContext , fullName string ) error {
2023-01-11 00:45:11 +08:00
valueKind := reflect . TypeOf ( mapValue ) . Kind ( )
if valueKind != reflect . String {
return fmt . Errorf ( "the value in map is not string, but %s" , valueKind )
}
2020-07-26 17:09:05 +08:00
2023-01-11 00:45:11 +08:00
options := opts . options ( )
if len ( options ) > 0 {
var checkValue string
switch mt := mapValue . ( type ) {
case string :
checkValue = mt
2023-01-11 15:21:39 +08:00
case fmt . Stringer :
2023-01-11 00:45:11 +08:00
checkValue = mt . String ( )
default :
return fmt . Errorf ( "the value in map is not string or json.Number, but %s" ,
valueKind . String ( ) )
2022-12-13 00:16:31 +08:00
}
2020-07-26 17:09:05 +08:00
2023-01-11 00:45:11 +08:00
if ! stringx . Contains ( options , checkValue ) {
2023-04-24 12:11:12 +08:00
return fmt . Errorf ( ` value "%s" for field %q is not defined in options "%v" ` ,
2023-01-11 00:45:11 +08:00
mapValue , key , options )
}
2022-12-13 00:16:31 +08:00
}
2023-01-11 00:45:11 +08:00
return fillPrimitive ( fieldType , value , mapValue , opts , fullName )
2022-12-13 00:16:31 +08:00
}
2022-12-11 00:41:50 +08:00
2022-12-13 00:16:31 +08:00
func ( u * Unmarshaler ) processNamedFieldWithoutValue ( fieldType reflect . Type , value reflect . Value ,
2024-05-11 23:06:59 +08:00
opts * fieldOptionsWithContext , fullName string ) error {
2022-12-13 00:16:31 +08:00
derefedType := Deref ( fieldType )
fieldKind := derefedType . Kind ( )
if defaultValue , ok := opts . getDefault ( ) ; ok {
if derefedType == durationType {
2023-01-12 15:56:51 +08:00
return fillDurationValue ( fieldType , value , defaultValue )
2022-12-13 00:16:31 +08:00
}
2022-12-11 00:41:50 +08:00
2022-12-13 00:16:31 +08:00
switch fieldKind {
case reflect . Array , reflect . Slice :
2023-07-23 20:10:41 +08:00
return u . fillSliceWithDefault ( derefedType , value , defaultValue , fullName )
2022-12-13 00:16:31 +08:00
default :
2023-01-12 15:56:51 +08:00
return setValueFromString ( fieldKind , value , defaultValue )
2022-12-13 00:16:31 +08:00
}
}
2020-07-26 17:09:05 +08:00
2023-03-02 17:20:09 +08:00
if u . opts . fillDefault {
2023-04-08 19:43:13 +08:00
if fieldType . Kind ( ) != reflect . Ptr && fieldKind == reflect . Struct {
return u . processFieldNotFromString ( fieldType , value , valueWithParent {
value : emptyMap ,
} , opts , fullName )
}
2023-03-02 17:20:09 +08:00
return nil
}
2022-12-13 00:16:31 +08:00
switch fieldKind {
2025-01-22 15:10:47 +08:00
case reflect . Array , reflect . Map , reflect . Slice :
2022-12-13 00:16:31 +08:00
if ! opts . optional ( ) {
return u . processFieldNotFromString ( fieldType , value , valueWithParent {
value : emptyMap ,
} , opts , fullName )
}
case reflect . Struct :
if ! opts . optional ( ) {
required , err := structValueRequired ( u . key , derefedType )
if err != nil {
return err
}
2022-12-11 00:41:50 +08:00
2022-12-13 00:16:31 +08:00
if required {
return fmt . Errorf ( "%q is not set" , fullName )
2020-07-26 17:09:05 +08:00
}
2022-12-13 00:16:31 +08:00
return u . processFieldNotFromString ( fieldType , value , valueWithParent {
value : emptyMap ,
} , opts , fullName )
}
default :
if ! opts . optional ( ) {
return newInitError ( fullName )
2020-07-26 17:09:05 +08:00
}
}
2022-12-13 00:16:31 +08:00
return nil
2020-07-26 17:09:05 +08:00
}
2024-12-23 00:56:20 +08:00
func ( u * Unmarshaler ) unmarshal ( i , v any , fullName string ) error {
valueType := reflect . TypeOf ( v )
if valueType . Kind ( ) != reflect . Ptr {
return errValueNotSettable
}
elemType := Deref ( valueType )
switch iv := i . ( type ) {
case map [ string ] any :
if elemType . Kind ( ) != reflect . Struct {
return errTypeMismatch
}
return u . unmarshalValuer ( mapValuer ( iv ) , v , fullName )
case [ ] any :
if elemType . Kind ( ) != reflect . Slice {
return errTypeMismatch
}
return u . fillSlice ( elemType , reflect . ValueOf ( v ) . Elem ( ) , iv , fullName )
default :
return errUnsupportedType
}
}
func ( u * Unmarshaler ) unmarshalValuer ( m Valuer , v any , fullName string ) error {
return u . unmarshalWithFullName ( simpleValuer { current : m } , v , fullName )
}
2023-01-24 16:32:02 +08:00
func ( u * Unmarshaler ) unmarshalWithFullName ( m valuerWithParent , v any , fullName string ) error {
2022-12-13 00:16:31 +08:00
rv := reflect . ValueOf ( v )
2023-07-30 21:37:41 +08:00
if err := ValidatePtr ( rv ) ; err != nil {
2022-12-13 00:16:31 +08:00
return err
2020-07-26 17:09:05 +08:00
}
2023-01-12 20:45:32 +08:00
valueType := reflect . TypeOf ( v )
baseType := Deref ( valueType )
if baseType . Kind ( ) != reflect . Struct {
2022-12-13 00:16:31 +08:00
return errValueNotStruct
2020-07-26 17:09:05 +08:00
}
2023-01-12 20:45:32 +08:00
valElem := rv . Elem ( )
if valElem . Kind ( ) == reflect . Ptr {
target := reflect . New ( baseType ) . Elem ( )
SetValue ( valueType . Elem ( ) , valElem , target )
valElem = target
}
numFields := baseType . NumField ( )
2022-12-13 00:16:31 +08:00
for i := 0 ; i < numFields ; i ++ {
2023-03-23 23:45:57 +08:00
typeField := baseType . Field ( i )
valueField := valElem . Field ( i )
if err := u . processField ( typeField , valueField , m , fullName ) ; err != nil {
2022-12-13 00:16:31 +08:00
return err
}
}
return nil
2020-07-26 17:09:05 +08:00
}
2022-11-04 21:55:17 +08:00
// WithStringValues customizes an Unmarshaler with number values from strings.
2020-07-26 17:09:05 +08:00
func WithStringValues ( ) UnmarshalOption {
return func ( opt * unmarshalOptions ) {
opt . fromString = true
}
}
2023-03-02 17:20:09 +08:00
// WithCanonicalKeyFunc customizes an Unmarshaler with Canonical Key func.
2021-08-10 17:38:03 +08:00
func WithCanonicalKeyFunc ( f func ( string ) string ) UnmarshalOption {
return func ( opt * unmarshalOptions ) {
opt . canonicalKey = f
}
}
2023-03-02 17:20:09 +08:00
// WithDefault customizes an Unmarshaler with fill default values.
func WithDefault ( ) UnmarshalOption {
return func ( opt * unmarshalOptions ) {
opt . fillDefault = true
}
}
2024-11-02 21:55:37 +08:00
// WithFromArray customizes an Unmarshaler with converting array values to non-array types.
// For example, if the field type is []string, and the value is [hello],
// the field type can be `string`, instead of `[]string`.
// Typically, this option is used for unmarshaling from form values.
func WithFromArray ( ) UnmarshalOption {
return func ( opt * unmarshalOptions ) {
opt . fromArray = true
}
}
2023-08-14 22:22:22 +08:00
// WithOpaqueKeys customizes an Unmarshaler with opaque keys.
// Opaque keys are keys that are not processed by the unmarshaler.
func WithOpaqueKeys ( ) UnmarshalOption {
return func ( opt * unmarshalOptions ) {
opt . opaqueKeys = true
}
}
2022-11-08 15:27:48 +08:00
func createValuer ( v valuerWithParent , opts * fieldOptionsWithContext ) valuerWithParent {
if opts . inherit ( ) {
return recursiveValuer {
current : v ,
parent : v . Parent ( ) ,
}
}
return simpleValuer {
current : v ,
parent : v . Parent ( ) ,
}
}
2023-01-12 15:56:51 +08:00
func fillDurationValue ( fieldType reflect . Type , value reflect . Value , dur string ) error {
2020-07-26 17:09:05 +08:00
d , err := time . ParseDuration ( dur )
if err != nil {
return err
}
2023-01-12 15:56:51 +08:00
SetValue ( fieldType , value , reflect . ValueOf ( d ) )
2020-07-26 17:09:05 +08:00
return nil
}
2023-01-24 16:32:02 +08:00
func fillPrimitive ( fieldType reflect . Type , value reflect . Value , mapValue any ,
2024-05-11 23:06:59 +08:00
opts * fieldOptionsWithContext , fullName string ) error {
2020-07-26 17:09:05 +08:00
if ! value . CanSet ( ) {
return errValueNotSettable
}
baseType := Deref ( fieldType )
if fieldType . Kind ( ) == reflect . Ptr {
target := reflect . New ( baseType ) . Elem ( )
switch mapValue . ( type ) {
case string , json . Number :
2023-01-12 15:56:51 +08:00
SetValue ( fieldType , value , target )
2020-07-26 17:09:05 +08:00
value = target
}
}
switch v := mapValue . ( type ) {
case string :
return validateAndSetValue ( baseType . Kind ( ) , value , v , opts )
case json . Number :
if err := validateJsonNumberRange ( v , opts ) ; err != nil {
return err
}
2023-01-12 15:56:51 +08:00
return setValueFromString ( baseType . Kind ( ) , value , v . String ( ) )
2020-07-26 17:09:05 +08:00
default :
return newTypeMismatchError ( fullName )
}
}
2023-01-24 16:32:02 +08:00
func fillWithSameType ( fieldType reflect . Type , value reflect . Value , mapValue any ,
2024-05-11 23:06:59 +08:00
opts * fieldOptionsWithContext ) error {
2020-07-26 17:09:05 +08:00
if ! value . CanSet ( ) {
return errValueNotSettable
}
if err := validateValueRange ( mapValue , opts ) ; err != nil {
return err
}
2022-12-13 00:16:31 +08:00
if fieldType . Kind ( ) == reflect . Ptr {
baseType := Deref ( fieldType )
2020-07-26 17:09:05 +08:00
target := reflect . New ( baseType ) . Elem ( )
2022-04-13 19:06:00 +08:00
setSameKindValue ( baseType , target , mapValue )
2023-01-12 15:56:51 +08:00
SetValue ( fieldType , value , target )
2020-07-26 17:09:05 +08:00
} else {
2022-12-13 00:16:31 +08:00
setSameKindValue ( fieldType , value , mapValue )
2020-07-26 17:09:05 +08:00
}
return nil
}
// getValue gets the value for the specific key, the key can be in the format of parentKey.childKey
2023-08-14 22:22:22 +08:00
func getValue ( m valuerWithParent , key string , opaque bool ) ( any , bool ) {
keys := readKeys ( key , opaque )
2020-07-26 17:09:05 +08:00
return getValueWithChainedKeys ( m , keys )
}
2023-01-24 16:32:02 +08:00
func getValueWithChainedKeys ( m valuerWithParent , keys [ ] string ) ( any , bool ) {
2022-11-08 15:27:48 +08:00
switch len ( keys ) {
case 0 :
return nil , false
case 1 :
2020-07-26 17:09:05 +08:00
v , ok := m . Value ( keys [ 0 ] )
return v , ok
2022-11-08 15:27:48 +08:00
default :
2020-07-26 17:09:05 +08:00
if v , ok := m . Value ( keys [ 0 ] ) ; ok {
2023-01-24 16:32:02 +08:00
if nextm , ok := v . ( map [ string ] any ) ; ok {
2022-11-08 15:27:48 +08:00
return getValueWithChainedKeys ( recursiveValuer {
current : mapValuer ( nextm ) ,
parent : m ,
} , keys [ 1 : ] )
2020-07-26 17:09:05 +08:00
}
}
2022-11-08 15:27:48 +08:00
return nil , false
}
2020-07-26 17:09:05 +08:00
}
func join ( elem ... string ) string {
var builder strings . Builder
var fillSep bool
for _ , e := range elem {
if len ( e ) == 0 {
continue
}
if fillSep {
builder . WriteByte ( delimiter )
} else {
fillSep = true
}
builder . WriteString ( e )
}
return builder . String ( )
}
2024-12-23 00:56:20 +08:00
func makeStringSlice ( refValue reflect . Value ) reflect . Value {
if refValue . Len ( ) != 1 {
return refValue
}
element := refValue . Index ( 0 )
if element . Kind ( ) != reflect . String {
return refValue
}
val , ok := element . Interface ( ) . ( string )
if ! ok {
return refValue
}
splits := strings . Split ( val , comma )
if len ( splits ) <= 1 {
return refValue
}
slice := reflect . MakeSlice ( stringSliceType , len ( splits ) , len ( splits ) )
for i , split := range splits {
// allow empty strings
slice . Index ( i ) . Set ( reflect . ValueOf ( split ) )
}
return slice
}
2020-07-26 17:09:05 +08:00
func newInitError ( name string ) error {
2023-04-24 12:11:12 +08:00
return fmt . Errorf ( "field %q is not set" , name )
2020-07-26 17:09:05 +08:00
}
func newTypeMismatchError ( name string ) error {
2023-04-24 12:11:12 +08:00
return fmt . Errorf ( "type mismatch for field %q" , name )
2020-07-26 17:09:05 +08:00
}
2023-07-12 01:08:09 +08:00
func newTypeMismatchErrorWithHint ( name , expectType , actualType string ) error {
return fmt . Errorf ( "type mismatch for field %q, expect %q, actual %q" ,
name , expectType , actualType )
2023-07-12 00:29:42 +08:00
}
2023-08-14 22:22:22 +08:00
func readKeys ( key string , opaque bool ) [ ] string {
if opaque {
return [ ] string { key }
}
2021-12-29 17:37:36 +08:00
cacheKeysLock . Lock ( )
keys , ok := cacheKeys [ key ]
cacheKeysLock . Unlock ( )
if ok {
2020-07-26 17:09:05 +08:00
return keys
}
2021-12-29 17:37:36 +08:00
keys = strings . FieldsFunc ( key , func ( c rune ) bool {
2020-07-26 17:09:05 +08:00
return c == delimiter
} )
2021-12-29 17:37:36 +08:00
cacheKeysLock . Lock ( )
cacheKeys [ key ] = keys
cacheKeysLock . Unlock ( )
2020-07-26 17:09:05 +08:00
return keys
}
2022-04-13 19:06:00 +08:00
2023-01-24 16:32:02 +08:00
func setSameKindValue ( targetType reflect . Type , target reflect . Value , value any ) {
2022-04-13 19:06:00 +08:00
if reflect . ValueOf ( value ) . Type ( ) . AssignableTo ( targetType ) {
target . Set ( reflect . ValueOf ( value ) )
} else {
target . Set ( reflect . ValueOf ( value ) . Convert ( targetType ) )
}
}