@@ -117,13 +117,6 @@ func UnmarshalManyPayload(in io.Reader, t reflect.Type) ([]interface{}, error) {
117117 return models , nil
118118}
119119
120- type unmarshal struct {
121- attribute interface {}
122- args []string
123- fieldType reflect.StructField
124- fieldValue reflect.Value
125- }
126-
127120func unmarshalNode (data * Node , model reflect.Value , included * map [string ]* Node ) (err error ) {
128121
129122 defer func () {
@@ -147,7 +140,6 @@ func unmarshalNode(data *Node, model reflect.Value, included *map[string]*Node)
147140 fieldValue := modelValue .Field (i )
148141
149142 args := strings .Split (tag , "," )
150-
151143 if len (args ) < 1 {
152144 er = ErrBadJSONAPIStructTag
153145 break
@@ -264,14 +256,7 @@ func unmarshalNode(data *Node, model reflect.Value, included *map[string]*Node)
264256 continue
265257 }
266258
267- data := unmarshal {
268- attribute ,
269- args ,
270- fieldType ,
271- fieldValue ,
272- }
273-
274- value , err := unmarshalAttribute (data )
259+ value , err := unmarshalAttribute (attribute , args , fieldType .Type , fieldValue )
275260 if err != nil {
276261 er = err
277262 break
@@ -378,45 +363,63 @@ func assign(field, value reflect.Value) {
378363 }
379364}
380365
381- func unmarshalAttribute (data unmarshal ) (value reflect.Value , err error ) {
366+ func unmarshalAttribute (attribute interface {}, args [] string , fieldType reflect. Type , fieldValue reflect. Value ) (value reflect.Value , err error ) {
382367
383- value = reflect .ValueOf (data . attribute )
368+ value = reflect .ValueOf (attribute )
384369
385370 // Handle field of type []string
386- if data . fieldValue .Type () == reflect .TypeOf ([]string {}) {
387- value , err = handleStringSlice (data )
371+ if fieldValue .Type () == reflect .TypeOf ([]string {}) {
372+ value , err = handleStringSlice (attribute , args , fieldType , fieldValue )
388373 return
389374 }
390375
391376 // Handle field of type time.Time
392- if data .fieldValue .Type () == reflect .TypeOf (time.Time {}) || data .fieldValue .Type () == reflect .TypeOf (new (time.Time )) {
393- value , err = handleTime (data )
377+ if fieldValue .Type () == reflect .TypeOf (time.Time {}) || fieldValue .Type () == reflect .TypeOf (new (time.Time )) {
378+ value , err = handleTime (attribute , args , fieldType , fieldValue )
379+ return
380+ }
381+
382+ // Handle field of type struct
383+ if fieldValue .Type ().Kind () == reflect .Struct {
384+ value , err = handleStruct (attribute , args , fieldType , fieldValue )
385+ return
386+ }
387+
388+ // Handle field of type struct
389+ if fieldValue .Type ().Kind () == reflect .Struct {
390+ value , err = handleStruct (attribute , args , fieldType , fieldValue )
391+ return
392+ }
393+
394+ // Handle field containing slice of structs
395+ if fieldValue .Type ().Kind () == reflect .Slice && reflect .TypeOf (fieldValue .Interface ()).Elem ().Kind () == reflect .Struct {
396+ value , err = handleStructSlice (attribute , args , fieldType , fieldValue )
394397 return
395398 }
396399
397400 // JSON value was a float (numeric)
398401 if value .Kind () == reflect .Float64 {
399- value , err = handleNumeric (data )
402+ value , err = handleNumeric (attribute , args , fieldType , fieldValue )
400403 return
401404 }
402405
403406 // Field was a Pointer type
404- if data . fieldValue .Kind () == reflect .Ptr {
405- value , err = handlePointer (data )
407+ if fieldValue .Kind () == reflect .Ptr {
408+ value , err = handlePointer (attribute , args , fieldType , fieldValue )
406409 return
407410 }
408411
409412 // As a final catch-all, ensure types line up to avoid a runtime panic.
410- if data . fieldValue .Kind () != value .Kind () {
413+ if fieldValue .Kind () != value .Kind () {
411414 err = ErrInvalidType
412415 return
413416 }
414417
415418 return
416419}
417420
418- func handleStringSlice (data unmarshal ) (reflect.Value , error ) {
419- v := reflect .ValueOf (data . attribute )
421+ func handleStringSlice (attribute interface {}, args [] string , fieldType reflect. Type , fieldValue reflect. Value ) (reflect.Value , error ) {
422+ v := reflect .ValueOf (attribute )
420423 values := make ([]string , v .Len ())
421424 for i := 0 ; i < v .Len (); i ++ {
422425 values [i ] = v .Index (i ).Interface ().(string )
@@ -425,13 +428,13 @@ func handleStringSlice(data unmarshal) (reflect.Value, error) {
425428 return reflect .ValueOf (values ), nil
426429}
427430
428- func handleTime (data unmarshal ) (reflect.Value , error ) {
431+ func handleTime (attribute interface {}, args [] string , fieldType reflect. Type , fieldValue reflect. Value ) (reflect.Value , error ) {
429432
430433 var isIso8601 bool
431- v := reflect .ValueOf (data . attribute )
434+ v := reflect .ValueOf (attribute )
432435
433- if len (data . args ) > 2 {
434- for _ , arg := range data . args [2 :] {
436+ if len (args ) > 2 {
437+ for _ , arg := range args [2 :] {
435438 if arg == annotationISO8601 {
436439 isIso8601 = true
437440 }
@@ -451,7 +454,7 @@ func handleTime(data unmarshal) (reflect.Value, error) {
451454 return reflect .ValueOf (time .Now ()), ErrInvalidISO8601
452455 }
453456
454- if data . fieldValue .Kind () == reflect .Ptr {
457+ if fieldValue .Kind () == reflect .Ptr {
455458 return reflect .ValueOf (& t ), nil
456459 }
457460
@@ -473,15 +476,15 @@ func handleTime(data unmarshal) (reflect.Value, error) {
473476 return reflect .ValueOf (t ), nil
474477}
475478
476- func handleNumeric (data unmarshal ) (reflect.Value , error ) {
477- v := reflect .ValueOf (data . attribute )
479+ func handleNumeric (attribute interface {}, args [] string , fieldType reflect. Type , fieldValue reflect. Value ) (reflect.Value , error ) {
480+ v := reflect .ValueOf (attribute )
478481 floatValue := v .Interface ().(float64 )
479482
480483 var kind reflect.Kind
481- if data . fieldValue .Kind () == reflect .Ptr {
482- kind = data . fieldType . Type .Elem ().Kind ()
484+ if fieldValue .Kind () == reflect .Ptr {
485+ kind = fieldType .Elem ().Kind ()
483486 } else {
484- kind = data . fieldType . Type .Kind ()
487+ kind = fieldType .Kind ()
485488 }
486489
487490 var numericValue reflect.Value
@@ -530,11 +533,11 @@ func handleNumeric(data unmarshal) (reflect.Value, error) {
530533 return numericValue , nil
531534}
532535
533- func handlePointer (data unmarshal ) (reflect.Value , error ) {
534- t := data . fieldValue .Type ()
536+ func handlePointer (attribute interface {}, args [] string , fieldType reflect. Type , fieldValue reflect. Value ) (reflect.Value , error ) {
537+ t := fieldValue .Type ()
535538 var concreteVal reflect.Value
536539
537- switch cVal := data . attribute .(type ) {
540+ switch cVal := attribute .(type ) {
538541 case string :
539542 concreteVal = reflect .ValueOf (& cVal )
540543 case bool :
@@ -555,3 +558,68 @@ func handlePointer(data unmarshal) (reflect.Value, error) {
555558
556559 return concreteVal , nil
557560}
561+
562+ func handleStruct (attribute interface {}, args []string , fieldType reflect.Type , fieldValue reflect.Value ) (reflect.Value , error ) {
563+ model := reflect .New (fieldValue .Type ())
564+
565+ modelValue := model .Elem ()
566+ modelType := model .Type ().Elem ()
567+
568+ var er error
569+
570+ for i := 0 ; i < modelValue .NumField (); i ++ {
571+ fieldType := modelType .Field (i )
572+ tag := fieldType .Tag .Get ("jsonapi" )
573+ if tag == "" {
574+ continue
575+ }
576+
577+ fieldValue := modelValue .Field (i )
578+
579+ args := strings .Split (tag , "," )
580+
581+ if len (args ) < 1 {
582+ er = ErrBadJSONAPIStructTag
583+ break
584+ }
585+
586+ if reflect .TypeOf (attribute ).Kind () != reflect .Map {
587+ return model , nil
588+ }
589+
590+ attributes := reflect .ValueOf (attribute ).Interface ().(map [string ]interface {})
591+ attribute := attributes [args [1 ]]
592+
593+ if attribute == nil {
594+ continue
595+ }
596+
597+ value , err := unmarshalAttribute (attribute , args , fieldType .Type , fieldValue )
598+ if err != nil {
599+ return model , nil
600+ }
601+
602+ assign (fieldValue , value )
603+ }
604+
605+ return model , er
606+ }
607+
608+ func handleStructSlice (attribute interface {}, args []string , fieldType reflect.Type , fieldValue reflect.Value ) (reflect.Value , error ) {
609+ models := reflect .New (fieldValue .Type ()).Elem ()
610+ dataMap := reflect .ValueOf (attribute ).Interface ().([]interface {})
611+ for _ , data := range dataMap {
612+ model := reflect .New (fieldValue .Type ().Elem ()).Elem ()
613+ modelType := model .Type ()
614+
615+ value , err := handleStruct (data , []string {}, modelType , model )
616+
617+ if err != nil {
618+ continue
619+ }
620+
621+ models = reflect .Append (models , reflect .Indirect (value ))
622+ }
623+
624+ return models , nil
625+ }
0 commit comments