@@ -60,6 +60,11 @@ func newErrUnsupportedPtrType(rf reflect.Value, t reflect.Type, structField refl
60
60
return ErrUnsupportedPtrType {rf , t , structField }
61
61
}
62
62
63
+ type includedNode struct {
64
+ node * Node
65
+ model * reflect.Value
66
+ }
67
+
63
68
// UnmarshalPayload converts an io into a struct instance using jsonapi tags on
64
69
// struct fields. This method supports single request payloads only, at the
65
70
// moment. Bulk creates and updates are not supported yet.
@@ -94,16 +99,16 @@ func newErrUnsupportedPtrType(rf reflect.Value, t reflect.Type, structField refl
94
99
// model interface{} should be a pointer to a struct.
95
100
func UnmarshalPayload (in io.Reader , model interface {}) error {
96
101
payload := new (OnePayload )
102
+ includedMap := make (map [string ]* includedNode )
97
103
98
104
if err := json .NewDecoder (in ).Decode (payload ); err != nil {
99
105
return err
100
106
}
101
107
102
108
if payload .Included != nil {
103
- includedMap := make (map [string ]* Node )
104
109
for _ , included := range payload .Included {
105
110
key := fmt .Sprintf ("%s,%s" , included .Type , included .ID )
106
- includedMap [key ] = included
111
+ includedMap [key ] = & includedNode { included , nil }
107
112
}
108
113
109
114
return unmarshalNode (payload .Data , reflect .ValueOf (model ), & includedMap )
@@ -120,13 +125,13 @@ func UnmarshalManyPayload(in io.Reader, t reflect.Type) ([]interface{}, error) {
120
125
return nil , err
121
126
}
122
127
123
- models := []interface {}{} // will be populated from the "data"
124
- includedMap := map [string ]* Node {} // will be populate from the "included"
128
+ models := []interface {}{} // will be populated from the "data"
129
+ includedMap := map [string ]* includedNode {} // will be populate from the "included"
125
130
126
131
if payload .Included != nil {
127
132
for _ , included := range payload .Included {
128
133
key := fmt .Sprintf ("%s,%s" , included .Type , included .ID )
129
- includedMap [key ] = included
134
+ includedMap [key ] = & includedNode { included , nil }
130
135
}
131
136
}
132
137
@@ -263,7 +268,7 @@ func getStructTags(field reflect.StructField) ([]string, error) {
263
268
264
269
// unmarshalNodeMaybeChoice populates a model that may or may not be
265
270
// a choice type struct that corresponds to a polyrelation or relation
266
- func unmarshalNodeMaybeChoice (m * reflect.Value , data * Node , annotation string , choiceTypeMapping map [string ]structFieldIndex , included * map [string ]* Node ) error {
271
+ func unmarshalNodeMaybeChoice (m * reflect.Value , data * Node , annotation string , choiceTypeMapping map [string ]structFieldIndex , included * map [string ]* includedNode ) error {
267
272
// This will hold either the value of the choice type model or the actual
268
273
// model, depending on annotation
269
274
var actualModel = * m
@@ -300,7 +305,7 @@ func unmarshalNodeMaybeChoice(m *reflect.Value, data *Node, annotation string, c
300
305
return nil
301
306
}
302
307
303
- func unmarshalNode (data * Node , model reflect.Value , included * map [string ]* Node ) (err error ) {
308
+ func unmarshalNode (data * Node , model reflect.Value , included * map [string ]* includedNode ) (err error ) {
304
309
defer func () {
305
310
if r := recover (); r != nil {
306
311
err = fmt .Errorf ("data is not a jsonapi representation of '%v'" , model .Type ())
@@ -509,6 +514,21 @@ func unmarshalNode(data *Node, model reflect.Value, included *map[string]*Node)
509
514
// model, depending on annotation
510
515
m := reflect .New (fieldValue .Type ().Elem ())
511
516
517
+ includedKey := fmt .Sprintf ("%s,%s" , relationship .Data .Type , relationship .Data .ID )
518
+ if included != nil && (* included )[includedKey ] != nil {
519
+ if (* included )[includedKey ].model != nil {
520
+ fieldValue .Set (* (* included )[includedKey ].model )
521
+ } else {
522
+ (* included )[includedKey ].model = & m
523
+ err := unmarshalNodeMaybeChoice (& m , (* included )[includedKey ].node , annotation , choiceMapping , included )
524
+ if err != nil {
525
+ er = err
526
+ break
527
+ }
528
+ fieldValue .Set (m )
529
+ }
530
+ continue
531
+ }
512
532
err = unmarshalNodeMaybeChoice (& m , relationship .Data , annotation , choiceMapping , included )
513
533
if err != nil {
514
534
er = err
@@ -565,11 +585,11 @@ func unmarshalNode(data *Node, model reflect.Value, included *map[string]*Node)
565
585
return er
566
586
}
567
587
568
- func fullNode (n * Node , included * map [string ]* Node ) * Node {
588
+ func fullNode (n * Node , included * map [string ]* includedNode ) * Node {
569
589
includedKey := fmt .Sprintf ("%s,%s" , n .Type , n .ID )
570
590
571
591
if included != nil && (* included )[includedKey ] != nil {
572
- return (* included )[includedKey ]
592
+ return (* included )[includedKey ]. node
573
593
}
574
594
575
595
return n
0 commit comments