Skip to content

Commit 0cac41a

Browse files
authored
chore: refactor mapping unmarshaler (#4145)
1 parent f10084a commit 0cac41a

File tree

2 files changed

+62
-28
lines changed

2 files changed

+62
-28
lines changed

core/mapping/unmarshaler.go

+37-27
Original file line numberDiff line numberDiff line change
@@ -113,27 +113,6 @@ func (u *Unmarshaler) unmarshalValuer(m Valuer, v any, fullName string) error {
113113
return u.unmarshalWithFullName(simpleValuer{current: m}, v, fullName)
114114
}
115115

116-
func (u *Unmarshaler) fillJsonUnmarshalerStruct(fieldType reflect.Type,
117-
value reflect.Value, targetValue string) error {
118-
if !value.CanSet() {
119-
return errValueNotSettable
120-
}
121-
122-
baseType := Deref(fieldType)
123-
target := reflect.New(baseType)
124-
unmarshaler, ok := target.Interface().(json.Unmarshaler)
125-
if !ok {
126-
return errUnsupportedType
127-
}
128-
129-
if err := unmarshaler.UnmarshalJSON([]byte(targetValue)); err != nil {
130-
return err
131-
}
132-
133-
value.Set(target)
134-
return nil
135-
}
136-
137116
func (u *Unmarshaler) fillMap(fieldType reflect.Type, value reflect.Value,
138117
mapValue any, fullName string) error {
139118
if !value.CanSet() {
@@ -330,6 +309,32 @@ func (u *Unmarshaler) fillSliceWithDefault(derefedType reflect.Type, value refle
330309
return u.fillSlice(derefedType, value, slice, fullName)
331310
}
332311

312+
func (u *Unmarshaler) fillUnmarshalerStruct(fieldType reflect.Type,
313+
value reflect.Value, targetValue string) error {
314+
if !value.CanSet() {
315+
return errValueNotSettable
316+
}
317+
318+
baseType := Deref(fieldType)
319+
target := reflect.New(baseType)
320+
switch u.key {
321+
case jsonTagKey:
322+
unmarshaler, ok := target.Interface().(json.Unmarshaler)
323+
if !ok {
324+
return errUnsupportedType
325+
}
326+
327+
if err := unmarshaler.UnmarshalJSON([]byte(targetValue)); err != nil {
328+
return err
329+
}
330+
default:
331+
return errUnsupportedType
332+
}
333+
334+
value.Set(target)
335+
return nil
336+
}
337+
333338
func (u *Unmarshaler) generateMap(keyType, elemType reflect.Type, mapValue any,
334339
fullName string) (reflect.Value, error) {
335340
mapType := reflect.MapOf(keyType, elemType)
@@ -423,6 +428,15 @@ func (u *Unmarshaler) generateMap(keyType, elemType reflect.Type, mapValue any,
423428
return targetValue, nil
424429
}
425430

431+
func (u *Unmarshaler) implementsUnmarshaler(t reflect.Type) bool {
432+
switch u.key {
433+
case jsonTagKey:
434+
return t.Implements(reflect.TypeOf((*json.Unmarshaler)(nil)).Elem())
435+
default:
436+
return false
437+
}
438+
}
439+
426440
func (u *Unmarshaler) parseOptionsWithContext(field reflect.StructField, m Valuer, fullName string) (
427441
string, *fieldOptionsWithContext, error) {
428442
key, options, err := parseKeyAndOptions(u.key, field)
@@ -600,8 +614,8 @@ func (u *Unmarshaler) processFieldNotFromString(fieldType reflect.Type, value re
600614
return u.fillSliceFromString(fieldType, value, mapValue, fullName)
601615
case valueKind == reflect.String && derefedFieldType == durationType:
602616
return fillDurationValue(fieldType, value, mapValue.(string))
603-
case valueKind == reflect.String && typeKind == reflect.Struct && implementsJsonUnmarshaler(fieldType):
604-
return u.fillJsonUnmarshalerStruct(fieldType, value, mapValue.(string))
617+
case valueKind == reflect.String && typeKind == reflect.Struct && u.implementsUnmarshaler(fieldType):
618+
return u.fillUnmarshalerStruct(fieldType, value, mapValue.(string))
605619
default:
606620
return u.processFieldPrimitive(fieldType, value, mapValue, opts, fullName)
607621
}
@@ -1087,10 +1101,6 @@ func getValueWithChainedKeys(m valuerWithParent, keys []string) (any, bool) {
10871101
}
10881102
}
10891103

1090-
func implementsJsonUnmarshaler(t reflect.Type) bool {
1091-
return t.Implements(reflect.TypeOf((*json.Unmarshaler)(nil)).Elem())
1092-
}
1093-
10941104
func join(elem ...string) string {
10951105
var builder strings.Builder
10961106

core/mapping/unmarshaler_test.go

+25-1
Original file line numberDiff line numberDiff line change
@@ -5761,7 +5761,7 @@ func TestUnmarshalWithIgnoreFields(t *testing.T) {
57615761
}
57625762
}
57635763

5764-
func TestUnmarshal_JsonUnmarshaler(t *testing.T) {
5764+
func TestUnmarshal_Unmarshaler(t *testing.T) {
57655765
t.Run("success", func(t *testing.T) {
57665766
v := struct {
57675767
Foo *mockUnmarshaler `json:"name"`
@@ -5778,6 +5778,30 @@ func TestUnmarshal_JsonUnmarshaler(t *testing.T) {
57785778
body := `{"name": "hello"}`
57795779
assert.Error(t, UnmarshalJsonBytes([]byte(body), &v))
57805780
})
5781+
5782+
t.Run("not json unmarshaler", func(t *testing.T) {
5783+
v := struct {
5784+
Foo *struct {
5785+
Name string
5786+
} `key:"name"`
5787+
}{}
5788+
u := NewUnmarshaler(defaultKeyName)
5789+
assert.Error(t, u.Unmarshal(map[string]any{
5790+
"name": "hello",
5791+
}, &v))
5792+
})
5793+
5794+
t.Run("not with json key", func(t *testing.T) {
5795+
v := struct {
5796+
Foo *mockUnmarshaler `json:"name"`
5797+
}{}
5798+
u := NewUnmarshaler(defaultKeyName)
5799+
// with different key, ignore
5800+
assert.NoError(t, u.Unmarshal(map[string]any{
5801+
"name": "hello",
5802+
}, &v))
5803+
assert.Nil(t, v.Foo)
5804+
})
57815805
}
57825806

57835807
func BenchmarkDefaultValue(b *testing.B) {

0 commit comments

Comments
 (0)