Skip to content

Commit 697dcb4

Browse files
skimatamarc-lebourdais
authored andcommitted
Embedded structs v3 (google#100)
* working version * fix text * combine test files * move private funcs to bottom * ErrInvalidType should ignore interfaces * replace MarshalOnePayload w/ MarshalPayload; fix bug w/ node merge() * minor tweaks; address a couple comments * decompose unmarshalNode() to smaller funcs; unmarshal should go from top-level to embedded * deep copy the node when passing relation/sideloaded notes to unmarshal() * add some comments and do some additional cleanup * add test uses annotationIgnore * implement support for struct fields that implement json.Marshaler/Unmarshaler * add additional test that compares marshal/unmarshal behavior w/ standard json library * add support for pointer embedded structs * Revert "implement support for struct fields that implement json.Marshaler/Unmarshaler" This reverts commit deeffb7.
1 parent e428b86 commit 697dcb4

File tree

5 files changed

+1030
-186
lines changed

5 files changed

+1030
-186
lines changed

constants.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const (
1010
annotationOmitEmpty = "omitempty"
1111
annotationISO8601 = "iso8601"
1212
annotationSeperator = ","
13+
annotationIgnore = "-"
1314

1415
iso8601TimeFormat = "2006-01-02T15:04:05Z"
1516

node.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,38 @@ type Node struct {
4444
Meta *Meta `json:"meta,omitempty"`
4545
}
4646

47+
func (n *Node) merge(node *Node) {
48+
if node.Type != "" {
49+
n.Type = node.Type
50+
}
51+
52+
if node.ID != "" {
53+
n.ID = node.ID
54+
}
55+
56+
if node.ClientID != "" {
57+
n.ClientID = node.ClientID
58+
}
59+
60+
if n.Attributes == nil && node.Attributes != nil {
61+
n.Attributes = make(map[string]interface{})
62+
}
63+
for k, v := range node.Attributes {
64+
n.Attributes[k] = v
65+
}
66+
67+
if n.Relationships == nil && node.Relationships != nil {
68+
n.Relationships = make(map[string]interface{})
69+
}
70+
for k, v := range node.Relationships {
71+
n.Relationships[k] = v
72+
}
73+
74+
if node.Links != nil {
75+
n.Links = node.Links
76+
}
77+
}
78+
4779
// RelationshipOneNode is used to represent a generic has one JSON API relation
4880
type RelationshipOneNode struct {
4981
Data *Node `json:"data"`
@@ -119,3 +151,35 @@ type RelationshipMetable interface {
119151
// JSONRelationshipMeta will be invoked for each relationship with the corresponding relation name (e.g. `comments`)
120152
JSONAPIRelationshipMeta(relation string) *Meta
121153
}
154+
155+
// derefs the arg, and clones the map-type attributes
156+
// note: maps are reference types, so they need an explicit copy.
157+
func deepCopyNode(n *Node) *Node {
158+
if n == nil {
159+
return n
160+
}
161+
162+
copyMap := func(m map[string]interface{}) map[string]interface{} {
163+
if m == nil {
164+
return m
165+
}
166+
cp := make(map[string]interface{})
167+
for k, v := range m {
168+
cp[k] = v
169+
}
170+
return cp
171+
}
172+
173+
copy := *n
174+
copy.Attributes = copyMap(copy.Attributes)
175+
copy.Relationships = copyMap(copy.Relationships)
176+
if copy.Links != nil {
177+
tmp := Links(copyMap(map[string]interface{}(*copy.Links)))
178+
copy.Links = &tmp
179+
}
180+
if copy.Meta != nil {
181+
tmp := Meta(copyMap(map[string]interface{}(*copy.Meta)))
182+
copy.Meta = &tmp
183+
}
184+
return &copy
185+
}

0 commit comments

Comments
 (0)