Skip to content

Commit 183003c

Browse files
committed
feat: support form array in three notations
Signed-off-by: kevin <[email protected]>
1 parent f57874a commit 183003c

File tree

7 files changed

+430
-91
lines changed

7 files changed

+430
-91
lines changed

core/mapping/unmarshaler.go

+100-45
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
)
1919

2020
const (
21+
comma = ","
2122
defaultKeyName = "key"
2223
delimiter = '.'
2324
ignoreKey = "-"
@@ -36,6 +37,7 @@ var (
3637
defaultCacheLock sync.Mutex
3738
emptyMap = map[string]any{}
3839
emptyValue = reflect.ValueOf(lang.Placeholder)
40+
stringSliceType = reflect.TypeOf([]string{})
3941
)
4042

4143
type (
@@ -80,40 +82,11 @@ func (u *Unmarshaler) Unmarshal(i, v any) error {
8082
return u.unmarshal(i, v, "")
8183
}
8284

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-
10885
// UnmarshalValuer unmarshals m into v.
10986
func (u *Unmarshaler) UnmarshalValuer(m Valuer, v any) error {
11087
return u.unmarshalValuer(simpleValuer{current: m}, v, "")
11188
}
11289

113-
func (u *Unmarshaler) unmarshalValuer(m Valuer, v any, fullName string) error {
114-
return u.unmarshalWithFullName(simpleValuer{current: m}, v, fullName)
115-
}
116-
11790
func (u *Unmarshaler) fillMap(fieldType reflect.Type, value reflect.Value,
11891
mapValue any, fullName string) error {
11992
if !value.CanSet() {
@@ -173,13 +146,18 @@ func (u *Unmarshaler) fillSlice(fieldType reflect.Type, value reflect.Value,
173146
baseType := fieldType.Elem()
174147
dereffedBaseType := Deref(baseType)
175148
dereffedBaseKind := dereffedBaseType.Kind()
176-
conv := reflect.MakeSlice(reflect.SliceOf(baseType), refValue.Len(), refValue.Cap())
177149
if refValue.Len() == 0 {
178-
value.Set(conv)
150+
value.Set(reflect.MakeSlice(reflect.SliceOf(baseType), 0, 0))
179151
return nil
180152
}
181153

154+
if u.opts.fromArray {
155+
refValue = makeStringSlice(refValue)
156+
}
157+
182158
var valid bool
159+
conv := reflect.MakeSlice(reflect.SliceOf(baseType), refValue.Len(), refValue.Cap())
160+
183161
for i := 0; i < refValue.Len(); i++ {
184162
ithValue := refValue.Index(i).Interface()
185163
if ithValue == nil {
@@ -191,17 +169,9 @@ func (u *Unmarshaler) fillSlice(fieldType reflect.Type, value reflect.Value,
191169

192170
switch dereffedBaseKind {
193171
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 {
201173
return err
202174
}
203-
204-
SetValue(fieldType.Elem(), conv.Index(i), target.Elem())
205175
case reflect.Slice:
206176
if err := u.fillSlice(dereffedBaseType, conv.Index(i), ithValue, sliceFullName); err != nil {
207177
return err
@@ -236,7 +206,7 @@ func (u *Unmarshaler) fillSliceFromString(fieldType reflect.Type, value reflect.
236206
return errUnsupportedType
237207
}
238208

239-
baseFieldType := Deref(fieldType.Elem())
209+
baseFieldType := fieldType.Elem()
240210
baseFieldKind := baseFieldType.Kind()
241211
conv := reflect.MakeSlice(reflect.SliceOf(baseFieldType), len(slice), cap(slice))
242212

@@ -257,29 +227,39 @@ func (u *Unmarshaler) fillSliceValue(slice reflect.Value, index int,
257227
}
258228

259229
ithVal := slice.Index(index)
230+
ithValType := ithVal.Type()
231+
260232
switch v := value.(type) {
261233
case fmt.Stringer:
262234
return setValueFromString(baseKind, ithVal, v.String())
263235
case string:
264236
return setValueFromString(baseKind, ithVal, v)
265237
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+
}
267247
default:
268248
// don't need to consider the difference between int, int8, int16, int32, int64,
269249
// uint, uint8, uint16, uint32, uint64, because they're handled as json.Number.
270250
if ithVal.Kind() == reflect.Ptr {
271-
baseType := Deref(ithVal.Type())
251+
baseType := Deref(ithValType)
272252
if !reflect.TypeOf(value).AssignableTo(baseType) {
273253
return errTypeMismatch
274254
}
275255

276256
target := reflect.New(baseType).Elem()
277257
target.Set(reflect.ValueOf(value))
278-
SetValue(ithVal.Type(), ithVal, target)
258+
SetValue(ithValType, ithVal, target)
279259
return nil
280260
}
281261

282-
if !reflect.TypeOf(value).AssignableTo(ithVal.Type()) {
262+
if !reflect.TypeOf(value).AssignableTo(ithValType) {
283263
return errTypeMismatch
284264
}
285265

@@ -310,6 +290,23 @@ func (u *Unmarshaler) fillSliceWithDefault(derefedType reflect.Type, value refle
310290
return u.fillSlice(derefedType, value, slice, fullName)
311291
}
312292

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+
313310
func (u *Unmarshaler) fillUnmarshalerStruct(fieldType reflect.Type,
314311
value reflect.Value, targetValue string) error {
315312
if !value.CanSet() {
@@ -952,6 +949,35 @@ func (u *Unmarshaler) processNamedFieldWithoutValue(fieldType reflect.Type, valu
952949
return nil
953950
}
954951

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+
955981
func (u *Unmarshaler) unmarshalWithFullName(m valuerWithParent, v any, fullName string) error {
956982
rv := reflect.ValueOf(v)
957983
if err := ValidatePtr(rv); err != nil {
@@ -1146,6 +1172,35 @@ func join(elem ...string) string {
11461172
return builder.String()
11471173
}
11481174

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+
11491204
func newInitError(name string) error {
11501205
return fmt.Errorf("field %q is not set", name)
11511206
}

0 commit comments

Comments
 (0)