major code simplification while making client ids work

This commit is contained in:
Sam Woodard 2015-09-17 15:55:53 -07:00
parent 10e0987b5d
commit d9645f7f7e
3 changed files with 38 additions and 62 deletions

View File

@ -1,6 +1,7 @@
package jsonapi
import (
"bytes"
"encoding/json"
"errors"
"fmt"
@ -178,16 +179,21 @@ func unmarshalNode(data *Node, model reflect.Value, included *map[string]*Node)
return false
}
relationship := reflect.ValueOf(data.Relationships[args[1]]).Interface().(map[string]interface{})
if isSlice {
data := relationship["data"].([]interface{})
relationship := new(RelationshipManyNode)
buf := bytes.NewBuffer(nil)
json.NewEncoder(buf).Encode(data.Relationships[args[1]])
json.NewDecoder(buf).Decode(relationship)
data := relationship.Data
models := reflect.New(fieldValue.Type()).Elem()
for _, r := range data {
for _, n := range data {
m := reflect.New(fieldValue.Type().Elem().Elem())
if err := unmarshalMap(r, m, included); err != nil {
if err := unmarshalNode(fullNode(n, included), m, included); err != nil {
er = err
return false
}
@ -197,8 +203,16 @@ func unmarshalNode(data *Node, model reflect.Value, included *map[string]*Node)
fieldValue.Set(models)
} else {
relationship := new(RelationshipOneNode)
buf := bytes.NewBuffer(nil)
json.NewEncoder(buf).Encode(data.Relationships[args[1]])
json.NewDecoder(buf).Decode(relationship)
m := reflect.New(fieldValue.Type().Elem())
if err := unmarshalMap(relationship["data"], m, included); err != nil {
if err := unmarshalNode(fullNode(relationship.Data, included), m, included); err != nil {
er = err
return false
}
@ -220,52 +234,12 @@ func unmarshalNode(data *Node, model reflect.Value, included *map[string]*Node)
return nil
}
func unmarshalMap(nodeData interface{}, model reflect.Value, included *map[string]*Node) error {
h := nodeData.(map[string]interface{})
node := fetchNode(h, included)
func fullNode(n *Node, included *map[string]*Node) *Node {
includedKey := fmt.Sprintf("%s,%s", n.Type, n.Id)
if err := unmarshalNode(node, model, included); err != nil {
return err
if included != nil && (*included)[includedKey] != nil {
return (*included)[includedKey]
}
return nil
}
func fetchNode(m map[string]interface{}, included *map[string]*Node) *Node {
var attributes map[string]interface{}
var relationships map[string]interface{}
if included != nil {
key := fmt.Sprintf("%s,%s", m["type"].(string), m["id"].(string))
node := (*included)[key]
if node != nil {
attributes = node.Attributes
relationships = node.Relationships
}
}
return mapToNode(m, attributes, relationships)
}
func mapToNode(m map[string]interface{}, attributes map[string]interface{}, relationships map[string]interface{}) *Node {
node := &Node{Type: m["type"].(string)}
if m["id"] != nil {
node.Id = m["id"].(string)
}
if m["attributes"] == nil {
node.Attributes = attributes
} else {
node.Attributes = m["attributes"].(map[string]interface{})
}
if m["relationships"] == nil {
node.Relationships = relationships
} else {
node.Relationships = m["relationships"].(map[string]interface{})
}
return node
return n
}

View File

@ -174,19 +174,14 @@ func TestUnmarshalNestedRelationshipsSideloaded(t *testing.T) {
}
func TestUnmarshalNestedRelationshipsEmbedded_withClientIDs(t *testing.T) {
out := bytes.NewBuffer(nil)
if err := MarshalOnePayloadEmbedded(out, testModel()); err != nil {
t.Fatal(err)
}
model := new(Blog)
if err := UnmarshalPayload(out, model); err != nil {
if err := UnmarshalPayload(samplePayload(), model); err != nil {
t.Fatal(err)
}
if model.ClientId == "" {
t.Fatalf("ClientId not set from request")
if model.Posts[0].ClientId == "" {
t.Fatalf("ClientId not set from request on related record")
}
}
@ -219,6 +214,7 @@ func samplePayload() io.Reader {
"title": "Foo",
"body": "Bar",
},
ClientId: "1",
},
&Node{
Type: "posts",
@ -226,6 +222,7 @@ func samplePayload() io.Reader {
"title": "X",
"body": "Y",
},
ClientId: "2",
},
},
},
@ -236,6 +233,7 @@ func samplePayload() io.Reader {
"title": "Bas",
"body": "Fuubar",
},
ClientId: "3",
Relationships: map[string]interface{}{
"comments": &RelationshipManyNode{
Data: []*Node{
@ -244,12 +242,14 @@ func samplePayload() io.Reader {
Attributes: map[string]interface{}{
"body": "Great post!",
},
ClientId: "4",
},
&Node{
Type: "comments",
Attributes: map[string]interface{}{
"body": "Needs some work!",
},
ClientId: "5",
},
},
},

View File

@ -22,6 +22,7 @@ type Post struct {
Blog
Id int `jsonapi:"primary,posts"`
BlogId int `jsonapi:"attr,blog_id"`
ClientId string `jsonapi:"client-id"`
Title string `jsonapi:"attr,title"`
Body string `jsonapi:"attr,body"`
Comments []*Comment `jsonapi:"relation,comments"`
@ -29,9 +30,10 @@ type Post struct {
}
type Comment struct {
Id int `jsonapi:"primary,comments"`
PostId int `jsonapi:"attr,post_id"`
Body string `jsonapi:"attr,body"`
Id int `jsonapi:"primary,comments"`
ClientId string `jsonapi:"client-id"`
PostId int `jsonapi:"attr,post_id"`
Body string `jsonapi:"attr,body"`
}
func TestHasPrimaryAnnotation(t *testing.T) {