@@ -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
0 commit comments