@@ -118,6 +118,7 @@ func UnmarshalManyPayload(in io.Reader, t reflect.Type) ([]interface{}, error) {
118118}
119119
120120func unmarshalNode (data * Node , model reflect.Value , included * map [string ]* Node ) (err error ) {
121+
121122 defer func () {
122123 if r := recover (); r != nil {
123124 err = fmt .Errorf ("data is not a jsonapi representation of '%v'" , model .Type ())
@@ -248,170 +249,71 @@ func unmarshalNode(data *Node, model reflect.Value, included *map[string]*Node)
248249 continue
249250 }
250251
251- var iso8601 bool
252+ var isIso8601 bool
252253
253254 if len (args ) > 2 {
254255 for _ , arg := range args [2 :] {
255256 if arg == annotationISO8601 {
256- iso8601 = true
257+ isIso8601 = true
257258 }
258259 }
259260 }
260261
261- val := attributes [args [1 ]]
262+ attribute := attributes [args [1 ]]
262263
263264 // continue if the attribute was not included in the request
264- if val == nil {
265+ if attribute == nil {
265266 continue
266267 }
267268
268- v := reflect .ValueOf (val )
269-
270- // Handle field of type time.Time
271- if fieldValue .Type () == reflect .TypeOf (time.Time {}) {
272- if iso8601 {
273- var tm string
274- if v .Kind () == reflect .String {
275- tm = v .Interface ().(string )
276- } else {
277- er = ErrInvalidISO8601
278- break
279- }
280-
281- t , err := time .Parse (iso8601TimeFormat , tm )
282- if err != nil {
283- er = ErrInvalidISO8601
284- break
285- }
286-
287- fieldValue .Set (reflect .ValueOf (t ))
288-
289- continue
290- }
291-
292- var at int64
293-
294- if v .Kind () == reflect .Float64 {
295- at = int64 (v .Interface ().(float64 ))
296- } else if v .Kind () == reflect .Int {
297- at = v .Int ()
298- } else {
299- return ErrInvalidTime
300- }
301-
302- t := time .Unix (at , 0 )
303-
304- fieldValue .Set (reflect .ValueOf (t ))
269+ value := reflect .ValueOf (attribute )
305270
271+ // Handle field of type []string
272+ if fieldValue .Type () == reflect .TypeOf ([]string {}) {
273+ values := handleStringSlice (value )
274+ assign (fieldValue , reflect .ValueOf (values ))
306275 continue
307276 }
308277
309- if fieldValue .Type () == reflect .TypeOf ([]string {}) {
310- values := make ([]string , v .Len ())
311- for i := 0 ; i < v .Len (); i ++ {
312- values [i ] = v .Index (i ).Interface ().(string )
278+ // Handle field of type time.Time
279+ if fieldValue .Type () == reflect .TypeOf (time.Time {}) {
280+ var time time.Time
281+ if time , err = handleTime (value , isIso8601 ); err != nil {
282+ er = err
283+ break
313284 }
314285
315- fieldValue .Set (reflect .ValueOf (values ))
316-
286+ assign (fieldValue , reflect .ValueOf (time ))
317287 continue
318288 }
319289
290+ // Handle field of type *time.Time
320291 if fieldValue .Type () == reflect .TypeOf (new (time.Time )) {
321- if iso8601 {
322- var tm string
323- if v .Kind () == reflect .String {
324- tm = v .Interface ().(string )
325- } else {
326- er = ErrInvalidISO8601
327- break
328- }
329-
330- v , err := time .Parse (iso8601TimeFormat , tm )
331- if err != nil {
332- er = ErrInvalidISO8601
333- break
334- }
335-
336- t := & v
337-
338- fieldValue .Set (reflect .ValueOf (t ))
339-
340- continue
341- }
342-
343- var at int64
344-
345- if v .Kind () == reflect .Float64 {
346- at = int64 (v .Interface ().(float64 ))
347- } else if v .Kind () == reflect .Int {
348- at = v .Int ()
349- } else {
350- return ErrInvalidTime
292+ var time time.Time
293+ if time , err = handleTime (value , isIso8601 ); err != nil {
294+ er = err
295+ break
351296 }
352297
353- v := time .Unix (at , 0 )
354- t := & v
355-
356- fieldValue .Set (reflect .ValueOf (t ))
357-
298+ assign (fieldValue , reflect .ValueOf (& time ))
358299 continue
359300 }
360301
361302 // JSON value was a float (numeric)
362- if v .Kind () == reflect .Float64 {
363- floatValue := v .Interface ().(float64 )
303+ if value .Kind () == reflect .Float64 {
364304
365- // The field may or may not be a pointer to a numeric; the kind var
366- // will not contain a pointer type
367305 var kind reflect.Kind
368306 if fieldValue .Kind () == reflect .Ptr {
369307 kind = fieldType .Type .Elem ().Kind ()
370308 } else {
371309 kind = fieldType .Type .Kind ()
372310 }
373311
374- var numericValue reflect.Value
375-
376- switch kind {
377- case reflect .Int :
378- n := int (floatValue )
379- numericValue = reflect .ValueOf (& n )
380- case reflect .Int8 :
381- n := int8 (floatValue )
382- numericValue = reflect .ValueOf (& n )
383- case reflect .Int16 :
384- n := int16 (floatValue )
385- numericValue = reflect .ValueOf (& n )
386- case reflect .Int32 :
387- n := int32 (floatValue )
388- numericValue = reflect .ValueOf (& n )
389- case reflect .Int64 :
390- n := int64 (floatValue )
391- numericValue = reflect .ValueOf (& n )
392- case reflect .Uint :
393- n := uint (floatValue )
394- numericValue = reflect .ValueOf (& n )
395- case reflect .Uint8 :
396- n := uint8 (floatValue )
397- numericValue = reflect .ValueOf (& n )
398- case reflect .Uint16 :
399- n := uint16 (floatValue )
400- numericValue = reflect .ValueOf (& n )
401- case reflect .Uint32 :
402- n := uint32 (floatValue )
403- numericValue = reflect .ValueOf (& n )
404- case reflect .Uint64 :
405- n := uint64 (floatValue )
406- numericValue = reflect .ValueOf (& n )
407- case reflect .Float32 :
408- n := float32 (floatValue )
409- numericValue = reflect .ValueOf (& n )
410- case reflect .Float64 :
411- n := floatValue
412- numericValue = reflect .ValueOf (& n )
413- default :
414- return ErrUnknownFieldNumberType
312+ numericValue , err := handleNumeric (value , kind )
313+
314+ if err != nil {
315+ er = err
316+ break
415317 }
416318
417319 assign (fieldValue , numericValue )
@@ -420,36 +322,23 @@ func unmarshalNode(data *Node, model reflect.Value, included *map[string]*Node)
420322
421323 // Field was a Pointer type
422324 if fieldValue .Kind () == reflect .Ptr {
423- var concreteVal reflect.Value
424-
425- switch cVal := val .(type ) {
426- case string :
427- concreteVal = reflect .ValueOf (& cVal )
428- case bool :
429- concreteVal = reflect .ValueOf (& cVal )
430- case complex64 :
431- concreteVal = reflect .ValueOf (& cVal )
432- case complex128 :
433- concreteVal = reflect .ValueOf (& cVal )
434- case uintptr :
435- concreteVal = reflect .ValueOf (& cVal )
436- default :
437- return ErrUnsupportedPtrType
438- }
439325
440- if fieldValue .Type () != concreteVal .Type () {
441- return ErrUnsupportedPtrType
326+ concreteVal , err := handlePointer (attribute , fieldValue .Type ())
327+
328+ if err != nil {
329+ er = err
330+ break
442331 }
443332
444- fieldValue . Set ( concreteVal )
333+ assign ( fieldValue , concreteVal )
445334 continue
446335 }
447336
448337 // As a final catch-all, ensure types line up to avoid a runtime panic.
449- if fieldValue .Kind () != v .Kind () {
338+ if fieldValue .Kind () != value .Kind () {
450339 return ErrInvalidType
451340 }
452- fieldValue . Set ( reflect .ValueOf (val ))
341+ assign ( fieldValue , reflect .ValueOf (attribute ))
453342
454343 } else if annotation == annotationRelation {
455344 isSlice := fieldValue .Type ().Kind () == reflect .Slice
@@ -548,3 +437,119 @@ func assign(field, value reflect.Value) {
548437 field .Set (reflect .Indirect (value ))
549438 }
550439}
440+
441+ func handleStringSlice (v reflect.Value ) []string {
442+ values := make ([]string , v .Len ())
443+ for i := 0 ; i < v .Len (); i ++ {
444+ values [i ] = v .Index (i ).Interface ().(string )
445+ }
446+
447+ return values
448+ }
449+
450+ func handleTime (v reflect.Value , isIso8601 bool ) (time.Time , error ) {
451+ if isIso8601 {
452+ var tm string
453+ if v .Kind () == reflect .String {
454+ tm = v .Interface ().(string )
455+ } else {
456+ return time .Now (), ErrInvalidISO8601
457+ }
458+
459+ t , err := time .Parse (iso8601TimeFormat , tm )
460+ if err != nil {
461+ return time .Now (), ErrInvalidISO8601
462+ }
463+
464+ return t , nil
465+ }
466+
467+ var at int64
468+
469+ if v .Kind () == reflect .Float64 {
470+ at = int64 (v .Interface ().(float64 ))
471+ } else if v .Kind () == reflect .Int {
472+ at = v .Int ()
473+ } else {
474+ return time .Now (), ErrInvalidTime
475+ }
476+
477+ t := time .Unix (at , 0 )
478+
479+ return t , nil
480+ }
481+
482+ func handleNumeric (v reflect.Value , kind reflect.Kind ) (reflect.Value , error ) {
483+
484+ floatValue := v .Interface ().(float64 )
485+
486+ var numericValue reflect.Value
487+
488+ switch kind {
489+ case reflect .Int :
490+ n := int (floatValue )
491+ numericValue = reflect .ValueOf (& n )
492+ case reflect .Int8 :
493+ n := int8 (floatValue )
494+ numericValue = reflect .ValueOf (& n )
495+ case reflect .Int16 :
496+ n := int16 (floatValue )
497+ numericValue = reflect .ValueOf (& n )
498+ case reflect .Int32 :
499+ n := int32 (floatValue )
500+ numericValue = reflect .ValueOf (& n )
501+ case reflect .Int64 :
502+ n := int64 (floatValue )
503+ numericValue = reflect .ValueOf (& n )
504+ case reflect .Uint :
505+ n := uint (floatValue )
506+ numericValue = reflect .ValueOf (& n )
507+ case reflect .Uint8 :
508+ n := uint8 (floatValue )
509+ numericValue = reflect .ValueOf (& n )
510+ case reflect .Uint16 :
511+ n := uint16 (floatValue )
512+ numericValue = reflect .ValueOf (& n )
513+ case reflect .Uint32 :
514+ n := uint32 (floatValue )
515+ numericValue = reflect .ValueOf (& n )
516+ case reflect .Uint64 :
517+ n := uint64 (floatValue )
518+ numericValue = reflect .ValueOf (& n )
519+ case reflect .Float32 :
520+ n := float32 (floatValue )
521+ numericValue = reflect .ValueOf (& n )
522+ case reflect .Float64 :
523+ n := floatValue
524+ numericValue = reflect .ValueOf (& n )
525+ default :
526+ return reflect.Value {}, ErrUnknownFieldNumberType
527+ }
528+
529+ return numericValue , nil
530+ }
531+
532+ func handlePointer (val interface {}, t reflect.Type ) (reflect.Value , error ) {
533+ var concreteVal reflect.Value
534+
535+ switch cVal := val .(type ) {
536+ case string :
537+ concreteVal = reflect .ValueOf (& cVal )
538+ case bool :
539+ concreteVal = reflect .ValueOf (& cVal )
540+ case complex64 :
541+ concreteVal = reflect .ValueOf (& cVal )
542+ case complex128 :
543+ concreteVal = reflect .ValueOf (& cVal )
544+ case uintptr :
545+ concreteVal = reflect .ValueOf (& cVal )
546+ default :
547+ return reflect.Value {}, ErrUnsupportedPtrType
548+ }
549+
550+ if t != concreteVal .Type () {
551+ return reflect.Value {}, ErrUnsupportedPtrType
552+ }
553+
554+ return concreteVal , nil
555+ }
0 commit comments