@@ -27,13 +27,24 @@ var (
27
27
// (numeric) but the Struct field was a non numeric type (i.e. not int, uint,
28
28
// float, etc)
29
29
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" )
33
30
// ErrInvalidType is returned when the given type is incompatible with the expected type.
34
31
ErrInvalidType = errors .New ("Invalid type provided" ) // I wish we used punctuation.
35
32
)
36
33
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 , t reflect.Type , structField reflect.StructField ) error {
37
+ typeName := t .Elem ().Name ()
38
+ kind := t .Elem ().Kind ()
39
+ if kind .String () != "" && kind .String () != typeName {
40
+ typeName = fmt .Sprintf ("%s (%s)" , typeName , kind .String ())
41
+ }
42
+ return fmt .Errorf (
43
+ "jsonapi: Can't unmarshal %+v (%s) to struct field `%s`, which is a pointer to `%s`" ,
44
+ rf , rf .Type ().Kind (), structField .Name , typeName ,
45
+ )
46
+ }
47
+
37
48
// UnmarshalPayload converts an io into a struct instance using jsonapi tags on
38
49
// struct fields. This method supports single request payloads only, at the
39
50
// moment. Bulk creates and updates are not supported yet.
@@ -256,7 +267,8 @@ func unmarshalNode(data *Node, model reflect.Value, included *map[string]*Node)
256
267
continue
257
268
}
258
269
259
- value , err := unmarshalAttribute (attribute , args , fieldType .Type , fieldValue )
270
+ structField := fieldType
271
+ value , err := unmarshalAttribute (attribute , args , structField , fieldValue )
260
272
if err != nil {
261
273
er = err
262
274
break
@@ -363,9 +375,10 @@ func assign(field, value reflect.Value) {
363
375
}
364
376
}
365
377
366
- func unmarshalAttribute (attribute interface {}, args []string , fieldType reflect.Type , fieldValue reflect.Value ) (value reflect.Value , err error ) {
378
+ func unmarshalAttribute (attribute interface {}, args []string , structField reflect.StructField , fieldValue reflect.Value ) (value reflect.Value , err error ) {
367
379
368
380
value = reflect .ValueOf (attribute )
381
+ fieldType := structField .Type
369
382
370
383
// Handle field of type []string
371
384
if fieldValue .Type () == reflect .TypeOf ([]string {}) {
@@ -399,7 +412,7 @@ func unmarshalAttribute(attribute interface{}, args []string, fieldType reflect.
399
412
400
413
// Field was a Pointer type
401
414
if fieldValue .Kind () == reflect .Ptr {
402
- value , err = handlePointer (attribute , args , fieldType , fieldValue )
415
+ value , err = handlePointer (attribute , args , fieldType , fieldValue , structField )
403
416
return
404
417
}
405
418
@@ -527,7 +540,7 @@ func handleNumeric(attribute interface{}, args []string, fieldType reflect.Type,
527
540
return numericValue , nil
528
541
}
529
542
530
- func handlePointer (attribute interface {}, args []string , fieldType reflect.Type , fieldValue reflect.Value ) (reflect.Value , error ) {
543
+ func handlePointer (attribute interface {}, args []string , fieldType reflect.Type , fieldValue reflect.Value , structField reflect. StructField ) (reflect.Value , error ) {
531
544
t := fieldValue .Type ()
532
545
var concreteVal reflect.Value
533
546
@@ -543,11 +556,11 @@ func handlePointer(attribute interface{}, args []string, fieldType reflect.Type,
543
556
case uintptr :
544
557
concreteVal = reflect .ValueOf (& cVal )
545
558
default :
546
- return reflect.Value {}, ErrUnsupportedPtrType
559
+ return reflect.Value {}, ErrUnsupportedPtrType ( reflect . ValueOf ( attribute ), fieldType , structField )
547
560
}
548
561
549
562
if t != concreteVal .Type () {
550
- return reflect.Value {}, ErrUnsupportedPtrType
563
+ return reflect.Value {}, ErrUnsupportedPtrType ( reflect . ValueOf ( attribute ), fieldType , structField )
551
564
}
552
565
553
566
return concreteVal , nil
0 commit comments