Skip to content

Commit cf7abfd

Browse files
committed
Show type for ErrUnsupportedPtrType
to aid in troubleshooting. Before: ``` Pointer type in struct is not supported ``` After: ``` [jsonapi unmarshalNode]: Can't unmarshal map[min_containers:2 max_containers:5] () to struct field `Scaling`, which is a pointer to `Scaling` (struct), which is not a supported type ```
1 parent 0400041 commit cf7abfd

File tree

2 files changed

+18
-10
lines changed

2 files changed

+18
-10
lines changed

request.go

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,19 @@ var (
2727
// (numeric) but the Struct field was a non numeric type (i.e. not int, uint,
2828
// float, etc)
2929
ErrUnknownFieldNumberType = errors.New("The struct field was not of a known number type")
30-
// ErrUnsupportedPtrType is returned when the Struct field was a pointer but
31-
// the JSON value was of a different type
32-
ErrUnsupportedPtrType = errors.New("Pointer type in struct is not supported")
3330
// ErrInvalidType is returned when the given type is incompatible with the expected type.
3431
ErrInvalidType = errors.New("Invalid type provided") // I wish we used punctuation.
3532
)
3633

34+
// ErrUnsupportedPtrType is returned when the Struct field was a pointer but
35+
// the JSON value was of a different type
36+
func ErrUnsupportedPtrType(rf reflect.Value, f reflect.Type, structField reflect.StructField) error {
37+
return fmt.Errorf(
38+
"[jsonapi unmarshalNode]: Can't unmarshal %+v (%s) to struct field `%s`, which is a pointer to `%s` (%s), which is not a supported type",
39+
rf, rf.Type().Name(), structField.Name, f.Elem().Name(), f.Elem().Kind(),
40+
)
41+
}
42+
3743
// UnmarshalPayload converts an io into a struct instance using jsonapi tags on
3844
// struct fields. This method supports single request payloads only, at the
3945
// moment. Bulk creates and updates are not supported yet.
@@ -256,7 +262,8 @@ func unmarshalNode(data *Node, model reflect.Value, included *map[string]*Node)
256262
continue
257263
}
258264

259-
value, err := unmarshalAttribute(attribute, args, fieldType.Type, fieldValue)
265+
structField := fieldType
266+
value, err := unmarshalAttribute(attribute, args, structField, fieldValue)
260267
if err != nil {
261268
er = err
262269
break
@@ -363,9 +370,10 @@ func assign(field, value reflect.Value) {
363370
}
364371
}
365372

366-
func unmarshalAttribute(attribute interface{}, args []string, fieldType reflect.Type, fieldValue reflect.Value) (value reflect.Value, err error) {
373+
func unmarshalAttribute(attribute interface{}, args []string, structField reflect.StructField, fieldValue reflect.Value) (value reflect.Value, err error) {
367374

368375
value = reflect.ValueOf(attribute)
376+
fieldType := structField.Type
369377

370378
// Handle field of type []string
371379
if fieldValue.Type() == reflect.TypeOf([]string{}) {
@@ -399,7 +407,7 @@ func unmarshalAttribute(attribute interface{}, args []string, fieldType reflect.
399407

400408
// Field was a Pointer type
401409
if fieldValue.Kind() == reflect.Ptr {
402-
value, err = handlePointer(attribute, args, fieldType, fieldValue)
410+
value, err = handlePointer(attribute, args, fieldType, fieldValue, structField)
403411
return
404412
}
405413

@@ -527,7 +535,7 @@ func handleNumeric(attribute interface{}, args []string, fieldType reflect.Type,
527535
return numericValue, nil
528536
}
529537

530-
func handlePointer(attribute interface{}, args []string, fieldType reflect.Type, fieldValue reflect.Value) (reflect.Value, error) {
538+
func handlePointer(attribute interface{}, args []string, fieldType reflect.Type, fieldValue reflect.Value, structField reflect.StructField) (reflect.Value, error) {
531539
t := fieldValue.Type()
532540
var concreteVal reflect.Value
533541

@@ -543,11 +551,11 @@ func handlePointer(attribute interface{}, args []string, fieldType reflect.Type,
543551
case uintptr:
544552
concreteVal = reflect.ValueOf(&cVal)
545553
default:
546-
return reflect.Value{}, ErrUnsupportedPtrType
554+
return reflect.Value{}, ErrUnsupportedPtrType(reflect.ValueOf(attribute), fieldType, structField)
547555
}
548556

549557
if t != concreteVal.Type() {
550-
return reflect.Value{}, ErrUnsupportedPtrType
558+
return reflect.Value{}, ErrUnsupportedPtrType(reflect.ValueOf(attribute), fieldType, structField)
551559
}
552560

553561
return concreteVal, nil

request_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ func TestUnmarshalToStructWithPointerAttr_BadType(t *testing.T) {
126126
in := map[string]interface{}{
127127
"name": true, // This is the wrong type.
128128
}
129-
expectedErrorMessage := ErrUnsupportedPtrType.Error()
129+
expectedErrorMessage := "[jsonapi unmarshalNode]: Can't unmarshal true (bool) to struct field `Name`, which is a pointer to `string` (string), which is not a supported type"
130130

131131
err := UnmarshalPayload(sampleWithPointerPayload(in), out)
132132

0 commit comments

Comments
 (0)