32
32
ErrUnknownFieldNumberType = errors .New ("The struct field was not of a known number type" )
33
33
// ErrInvalidType is returned when the given type is incompatible with the expected type.
34
34
ErrInvalidType = errors .New ("Invalid type provided" ) // I wish we used punctuation.
35
+ // ErrTypeNotFound is returned when the given type not found on the model.
36
+ ErrTypeNotFound = errors .New ("no primary type annotation found on model" )
35
37
)
36
38
37
39
// ErrUnsupportedPtrType is returned when the Struct field was a pointer but
@@ -155,7 +157,13 @@ func jsonapiTypeOfModel(structModel reflect.Type) (string, error) {
155
157
for i := 0 ; i < structModel .NumField (); i ++ {
156
158
fieldType := structModel .Field (i )
157
159
args , err := getStructTags (fieldType )
158
- if err != nil || len (args ) < 2 {
160
+
161
+ // A jsonapi tag was found, but it was improperly structured
162
+ if err != nil {
163
+ return "" , err
164
+ }
165
+
166
+ if len (args ) < 2 {
159
167
continue
160
168
}
161
169
@@ -164,7 +172,7 @@ func jsonapiTypeOfModel(structModel reflect.Type) (string, error) {
164
172
}
165
173
}
166
174
167
- return "" , errors . New ( "no primary annotation found on model" )
175
+ return "" , ErrTypeNotFound
168
176
}
169
177
170
178
// structFieldIndex holds a bit of information about a type found at a struct field index
@@ -175,15 +183,31 @@ type structFieldIndex struct {
175
183
176
184
// choiceStructMapping reflects on a value that may be a slice
177
185
// of choice type structs or a choice type struct. A choice type
178
- // struct is a struct comprising of pointers to other jsonapi models,
186
+ // struct is a struct comprised of pointers to other jsonapi models,
179
187
// only one of which is populated with a value by the decoder.
180
188
//
181
189
// The specified type is probed and a map is generated that maps the
182
190
// underlying model type (its 'primary' type) to the field number
183
191
// within the choice type struct. This data can then be used to correctly
184
192
// assign each data relationship node to the correct choice type
185
193
// struct field.
186
- func choiceStructMapping (choice reflect.Type ) (result map [string ]structFieldIndex , err error ) {
194
+ //
195
+ // For example, if the `choice` type was
196
+ //
197
+ // type OneOfMedia struct {
198
+ // Video *Video
199
+ // Image *Image
200
+ // }
201
+ //
202
+ // then the resulting map would be
203
+ //
204
+ // {
205
+ // "videos" => {Video, 0}
206
+ // "images" => {Image, 1}
207
+ // }
208
+ //
209
+ // where `"videos"` is the value of the `primary` annotation on the `Video` model
210
+ func choiceStructMapping (choice reflect.Type ) (result map [string ]structFieldIndex ) {
187
211
result = make (map [string ]structFieldIndex )
188
212
189
213
for choice .Kind () != reflect .Struct {
@@ -213,7 +237,7 @@ func choiceStructMapping(choice reflect.Type) (result map[string]structFieldInde
213
237
}
214
238
}
215
239
216
- return result , nil
240
+ return result
217
241
}
218
242
219
243
func getStructTags (field reflect.StructField ) ([]string , error ) {
@@ -395,11 +419,7 @@ func unmarshalNode(data *Node, model reflect.Value, included *map[string]*Node)
395
419
// struct type field.
396
420
var choiceMapping map [string ]structFieldIndex = nil
397
421
if annotation == annotationPolyRelation {
398
- choiceMapping , err = choiceStructMapping (fieldValue .Type ())
399
- if err != nil {
400
- er = err
401
- break
402
- }
422
+ choiceMapping = choiceStructMapping (fieldValue .Type ())
403
423
}
404
424
405
425
if isSlice {
0 commit comments