From 662431e860691395a594fb558111b9ac3f5a8fa0 Mon Sep 17 00:00:00 2001 From: skimata Date: Tue, 1 Aug 2017 11:48:27 -0700 Subject: [PATCH] Feature/embeded structs fix tests (#105) * fix TestEmbededStructs_nonNilStructPtr; bug on loop w/ (multiple) embedded structs; should just continue on success * fix TestMarshal_duplicatePrimaryAnnotationFromEmbeddedStructs; fix order of processing of visitModelNode --- request.go | 8 +++++--- response.go | 25 ++++++++++++++++++++++--- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/request.go b/request.go index 9e0eb1a..e962943 100644 --- a/request.go +++ b/request.go @@ -218,10 +218,12 @@ func unmarshalNode(data *Node, model reflect.Value, included *map[string]*Node) assign(em.structField, tmp) data = copy } - return nil + } else { + // handle non-nil scenarios + if err := unmarshalNode(data, em.model, included); err != nil { + return err + } } - // handle non-nil scenarios - return unmarshalNode(data, em.model, included) } return nil diff --git a/response.go b/response.go index 2e9acd7..a19848a 100644 --- a/response.go +++ b/response.go @@ -202,8 +202,10 @@ func MarshalOnePayloadEmbedded(w io.Writer, model interface{}) error { return nil } -func visitModelNode(model interface{}, included *map[string]*Node, - sideload bool) (*Node, error) { +// visitModelNode converts models to jsonapi payloads +// it handles the deepest models first. (i.e.) embedded models +// this is so that upper-level attributes can overwrite lower-level attributes +func visitModelNode(model interface{}, included *map[string]*Node, sideload bool) (*Node, error) { node := new(Node) var er error @@ -211,12 +213,13 @@ func visitModelNode(model interface{}, included *map[string]*Node, modelValue := reflect.ValueOf(model).Elem() modelType := reflect.ValueOf(model).Type().Elem() + // handle just the embedded models first for i := 0; i < modelValue.NumField(); i++ { fieldValue := modelValue.Field(i) fieldType := modelType.Field(i) + // skip if annotated w/ ignore tag := fieldType.Tag.Get(annotationJSONAPI) - if shouldIgnoreField(tag) { continue } @@ -239,6 +242,22 @@ func visitModelNode(model interface{}, included *map[string]*Node, break } node.merge(embNode) + } + } + + // handle everthing else + for i := 0; i < modelValue.NumField(); i++ { + fieldValue := modelValue.Field(i) + fieldType := modelType.Field(i) + + tag := fieldType.Tag.Get(annotationJSONAPI) + + if shouldIgnoreField(tag) { + continue + } + + // skip embedded because it was handled in a previous loop + if isEmbeddedStruct(fieldType) || isEmbeddedStructPtr(fieldType) { continue }