From d9645f7f7e07370fefda8cc664102f64a947b7ba Mon Sep 17 00:00:00 2001 From: Sam Woodard Date: Thu, 17 Sep 2015 15:55:53 -0700 Subject: [PATCH] major code simplification while making client ids work --- request.go | 76 ++++++++++++++++-------------------------------- request_test.go | 16 +++++----- response_test.go | 8 +++-- 3 files changed, 38 insertions(+), 62 deletions(-) diff --git a/request.go b/request.go index 4f3d7f0..e73a571 100644 --- a/request.go +++ b/request.go @@ -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 } diff --git a/request_test.go b/request_test.go index 0f4a9ee..f96d805 100644 --- a/request_test.go +++ b/request_test.go @@ -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", }, }, }, diff --git a/response_test.go b/response_test.go index 2a75003..bbafa99 100644 --- a/response_test.go +++ b/response_test.go @@ -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) {