@@ -18,6 +18,7 @@ import (
18
18
)
19
19
20
20
const (
21
+ comma = ","
21
22
defaultKeyName = "key"
22
23
delimiter = '.'
23
24
ignoreKey = "-"
36
37
defaultCacheLock sync.Mutex
37
38
emptyMap = map [string ]any {}
38
39
emptyValue = reflect .ValueOf (lang .Placeholder )
40
+ stringSliceType = reflect .TypeOf ([]string {})
39
41
)
40
42
41
43
type (
@@ -80,40 +82,11 @@ func (u *Unmarshaler) Unmarshal(i, v any) error {
80
82
return u .unmarshal (i , v , "" )
81
83
}
82
84
83
- func (u * Unmarshaler ) unmarshal (i , v any , fullName string ) error {
84
- valueType := reflect .TypeOf (v )
85
- if valueType .Kind () != reflect .Ptr {
86
- return errValueNotSettable
87
- }
88
-
89
- elemType := Deref (valueType )
90
- switch iv := i .(type ) {
91
- case map [string ]any :
92
- if elemType .Kind () != reflect .Struct {
93
- return errTypeMismatch
94
- }
95
-
96
- return u .unmarshalValuer (mapValuer (iv ), v , fullName )
97
- case []any :
98
- if elemType .Kind () != reflect .Slice {
99
- return errTypeMismatch
100
- }
101
-
102
- return u .fillSlice (elemType , reflect .ValueOf (v ).Elem (), iv , fullName )
103
- default :
104
- return errUnsupportedType
105
- }
106
- }
107
-
108
85
// UnmarshalValuer unmarshals m into v.
109
86
func (u * Unmarshaler ) UnmarshalValuer (m Valuer , v any ) error {
110
87
return u .unmarshalValuer (simpleValuer {current : m }, v , "" )
111
88
}
112
89
113
- func (u * Unmarshaler ) unmarshalValuer (m Valuer , v any , fullName string ) error {
114
- return u .unmarshalWithFullName (simpleValuer {current : m }, v , fullName )
115
- }
116
-
117
90
func (u * Unmarshaler ) fillMap (fieldType reflect.Type , value reflect.Value ,
118
91
mapValue any , fullName string ) error {
119
92
if ! value .CanSet () {
@@ -173,13 +146,18 @@ func (u *Unmarshaler) fillSlice(fieldType reflect.Type, value reflect.Value,
173
146
baseType := fieldType .Elem ()
174
147
dereffedBaseType := Deref (baseType )
175
148
dereffedBaseKind := dereffedBaseType .Kind ()
176
- conv := reflect .MakeSlice (reflect .SliceOf (baseType ), refValue .Len (), refValue .Cap ())
177
149
if refValue .Len () == 0 {
178
- value .Set (conv )
150
+ value .Set (reflect . MakeSlice ( reflect . SliceOf ( baseType ), 0 , 0 ) )
179
151
return nil
180
152
}
181
153
154
+ if u .opts .fromArray {
155
+ refValue = makeStringSlice (refValue )
156
+ }
157
+
182
158
var valid bool
159
+ conv := reflect .MakeSlice (reflect .SliceOf (baseType ), refValue .Len (), refValue .Cap ())
160
+
183
161
for i := 0 ; i < refValue .Len (); i ++ {
184
162
ithValue := refValue .Index (i ).Interface ()
185
163
if ithValue == nil {
@@ -191,17 +169,9 @@ func (u *Unmarshaler) fillSlice(fieldType reflect.Type, value reflect.Value,
191
169
192
170
switch dereffedBaseKind {
193
171
case reflect .Struct :
194
- target := reflect .New (dereffedBaseType )
195
- val , ok := ithValue .(map [string ]any )
196
- if ! ok {
197
- return errTypeMismatch
198
- }
199
-
200
- if err := u .unmarshal (val , target .Interface (), sliceFullName ); err != nil {
172
+ if err := u .fillStructElement (baseType , conv .Index (i ), ithValue , sliceFullName ); err != nil {
201
173
return err
202
174
}
203
-
204
- SetValue (fieldType .Elem (), conv .Index (i ), target .Elem ())
205
175
case reflect .Slice :
206
176
if err := u .fillSlice (dereffedBaseType , conv .Index (i ), ithValue , sliceFullName ); err != nil {
207
177
return err
@@ -236,7 +206,7 @@ func (u *Unmarshaler) fillSliceFromString(fieldType reflect.Type, value reflect.
236
206
return errUnsupportedType
237
207
}
238
208
239
- baseFieldType := Deref ( fieldType .Elem () )
209
+ baseFieldType := fieldType .Elem ()
240
210
baseFieldKind := baseFieldType .Kind ()
241
211
conv := reflect .MakeSlice (reflect .SliceOf (baseFieldType ), len (slice ), cap (slice ))
242
212
@@ -257,29 +227,39 @@ func (u *Unmarshaler) fillSliceValue(slice reflect.Value, index int,
257
227
}
258
228
259
229
ithVal := slice .Index (index )
230
+ ithValType := ithVal .Type ()
231
+
260
232
switch v := value .(type ) {
261
233
case fmt.Stringer :
262
234
return setValueFromString (baseKind , ithVal , v .String ())
263
235
case string :
264
236
return setValueFromString (baseKind , ithVal , v )
265
237
case map [string ]any :
266
- return u .fillMap (ithVal .Type (), ithVal , value , fullName )
238
+ // deref to handle both pointer and non-pointer types.
239
+ switch Deref (ithValType ).Kind () {
240
+ case reflect .Struct :
241
+ return u .fillStructElement (ithValType , ithVal , v , fullName )
242
+ case reflect .Map :
243
+ return u .fillMap (ithValType , ithVal , value , fullName )
244
+ default :
245
+ return errTypeMismatch
246
+ }
267
247
default :
268
248
// don't need to consider the difference between int, int8, int16, int32, int64,
269
249
// uint, uint8, uint16, uint32, uint64, because they're handled as json.Number.
270
250
if ithVal .Kind () == reflect .Ptr {
271
- baseType := Deref (ithVal . Type () )
251
+ baseType := Deref (ithValType )
272
252
if ! reflect .TypeOf (value ).AssignableTo (baseType ) {
273
253
return errTypeMismatch
274
254
}
275
255
276
256
target := reflect .New (baseType ).Elem ()
277
257
target .Set (reflect .ValueOf (value ))
278
- SetValue (ithVal . Type () , ithVal , target )
258
+ SetValue (ithValType , ithVal , target )
279
259
return nil
280
260
}
281
261
282
- if ! reflect .TypeOf (value ).AssignableTo (ithVal . Type () ) {
262
+ if ! reflect .TypeOf (value ).AssignableTo (ithValType ) {
283
263
return errTypeMismatch
284
264
}
285
265
@@ -310,6 +290,23 @@ func (u *Unmarshaler) fillSliceWithDefault(derefedType reflect.Type, value refle
310
290
return u .fillSlice (derefedType , value , slice , fullName )
311
291
}
312
292
293
+ func (u * Unmarshaler ) fillStructElement (baseType reflect.Type , target reflect.Value ,
294
+ value any , fullName string ) error {
295
+ val , ok := value .(map [string ]any )
296
+ if ! ok {
297
+ return errTypeMismatch
298
+ }
299
+
300
+ // use Deref(baseType) to get the base type in case the type is a pointer type.
301
+ ptr := reflect .New (Deref (baseType ))
302
+ if err := u .unmarshal (val , ptr .Interface (), fullName ); err != nil {
303
+ return err
304
+ }
305
+
306
+ SetValue (baseType , target , ptr .Elem ())
307
+ return nil
308
+ }
309
+
313
310
func (u * Unmarshaler ) fillUnmarshalerStruct (fieldType reflect.Type ,
314
311
value reflect.Value , targetValue string ) error {
315
312
if ! value .CanSet () {
@@ -952,6 +949,35 @@ func (u *Unmarshaler) processNamedFieldWithoutValue(fieldType reflect.Type, valu
952
949
return nil
953
950
}
954
951
952
+ func (u * Unmarshaler ) unmarshal (i , v any , fullName string ) error {
953
+ valueType := reflect .TypeOf (v )
954
+ if valueType .Kind () != reflect .Ptr {
955
+ return errValueNotSettable
956
+ }
957
+
958
+ elemType := Deref (valueType )
959
+ switch iv := i .(type ) {
960
+ case map [string ]any :
961
+ if elemType .Kind () != reflect .Struct {
962
+ return errTypeMismatch
963
+ }
964
+
965
+ return u .unmarshalValuer (mapValuer (iv ), v , fullName )
966
+ case []any :
967
+ if elemType .Kind () != reflect .Slice {
968
+ return errTypeMismatch
969
+ }
970
+
971
+ return u .fillSlice (elemType , reflect .ValueOf (v ).Elem (), iv , fullName )
972
+ default :
973
+ return errUnsupportedType
974
+ }
975
+ }
976
+
977
+ func (u * Unmarshaler ) unmarshalValuer (m Valuer , v any , fullName string ) error {
978
+ return u .unmarshalWithFullName (simpleValuer {current : m }, v , fullName )
979
+ }
980
+
955
981
func (u * Unmarshaler ) unmarshalWithFullName (m valuerWithParent , v any , fullName string ) error {
956
982
rv := reflect .ValueOf (v )
957
983
if err := ValidatePtr (rv ); err != nil {
@@ -1146,6 +1172,35 @@ func join(elem ...string) string {
1146
1172
return builder .String ()
1147
1173
}
1148
1174
1175
+ func makeStringSlice (refValue reflect.Value ) reflect.Value {
1176
+ if refValue .Len () != 1 {
1177
+ return refValue
1178
+ }
1179
+
1180
+ element := refValue .Index (0 )
1181
+ if element .Kind () != reflect .String {
1182
+ return refValue
1183
+ }
1184
+
1185
+ val , ok := element .Interface ().(string )
1186
+ if ! ok {
1187
+ return refValue
1188
+ }
1189
+
1190
+ splits := strings .Split (val , comma )
1191
+ if len (splits ) <= 1 {
1192
+ return refValue
1193
+ }
1194
+
1195
+ slice := reflect .MakeSlice (stringSliceType , len (splits ), len (splits ))
1196
+ for i , split := range splits {
1197
+ // allow empty strings
1198
+ slice .Index (i ).Set (reflect .ValueOf (split ))
1199
+ }
1200
+
1201
+ return slice
1202
+ }
1203
+
1149
1204
func newInitError (name string ) error {
1150
1205
return fmt .Errorf ("field %q is not set" , name )
1151
1206
}
0 commit comments