diff --git a/node.go b/node.go index 51c658b..236f81e 100644 --- a/node.go +++ b/node.go @@ -20,7 +20,7 @@ type JsonApiNode struct { Type string `json:"type"` Id string `json:"id"` Attributes map[string]interface{} `json:"attributes,omitempty"` - Relationships map[string]interface{} `json:"realtionships,omitempty"` + Relationships map[string]interface{} `json:"relationships,omitempty"` } type JsonApiRelationshipOneNode struct { diff --git a/request.go b/request.go index c6ad9eb..03a7d0d 100644 --- a/request.go +++ b/request.go @@ -1,15 +1,23 @@ package jsonapi import ( + "encoding/json" "errors" "fmt" + "io" "reflect" "strconv" "strings" "time" ) -func UnmarshalJsonApiPayload(payload *JsonApiOnePayload, model interface{}) error { +func UnmarshalJsonApiPayload(in io.Reader, model interface{}) error { + payload := new(JsonApiOnePayload) + + if err := json.NewDecoder(in).Decode(payload); err != nil { + return err + } + return unmarshalJsonApiNode(payload.Data, reflect.ValueOf(model)) } @@ -20,7 +28,6 @@ func unmarshalJsonApiNode(data *JsonApiNode, model reflect.Value) error { var er error var i = 0 - fmt.Printf("%v,%v\n", model.Type(), modelType) modelType.FieldByNameFunc(func(name string) bool { if er != nil { return false diff --git a/request_test.go b/request_test.go index fd8518e..56b4b1b 100644 --- a/request_test.go +++ b/request_test.go @@ -3,7 +3,7 @@ package jsonapi import ( "bytes" "encoding/json" - "fmt" + "io" "testing" ) @@ -28,10 +28,10 @@ func TestUnmarshalSetsAttrs(t *testing.T) { t.Fatal(err) } - o := bytes.NewBuffer(nil) - json.NewEncoder(o).Encode(out) + //o := bytes.NewBuffer(nil) + //json.NewEncoder(o).Encode(out) - fmt.Printf("%s\n", o.Bytes()) + //fmt.Printf("%s\n", o.Bytes()) if out.CreatedAt.IsZero() { t.Fatalf("Did not parse time") @@ -42,7 +42,49 @@ func TestUnmarshalSetsAttrs(t *testing.T) { } } -func samplePayload() *JsonApiOnePayload { +func TestUnmarshalRelationships(t *testing.T) { + in := samplePayload() + out := new(Blog) + + if err := UnmarshalJsonApiPayload(in, out); err != nil { + t.Fatal(err) + } + + if out.CurrentPost == nil { + t.Fatalf("Current post was not materialized") + } + + if out.CurrentPost.Title != "Bas" || out.CurrentPost.Body != "Fuubar" { + t.Fatalf("Attributes where not set") + } + + if len(out.Posts) != 2 { + t.Fatalf("There should have been 2 posts") + } +} + +func TestUnmarshalNestedRelationships(t *testing.T) { + in := samplePayload() + out := new(Blog) + + if err := UnmarshalJsonApiPayload(in, out); err != nil { + t.Fatal(err) + } + + if out.CurrentPost == nil { + t.Fatalf("Current post was not materialized") + } + + if out.CurrentPost.Comments == nil { + t.Fatalf("Did not materialize nested records, comments") + } + + if len(out.CurrentPost.Comments) != 2 { + t.Fatalf("Wrong number of comments") + } +} + +func samplePayload() io.Reader { payload := &JsonApiOnePayload{ Data: &JsonApiNode{ Type: "blogs", @@ -61,6 +103,13 @@ func samplePayload() *JsonApiOnePayload { "body": "Bar", }, }, + &JsonApiNode{ + Type: "posts", + Attributes: map[string]interface{}{ + "title": "X", + "body": "Y", + }, + }, }, }, "current_post": &JsonApiRelationshipOneNode{ @@ -70,6 +119,24 @@ func samplePayload() *JsonApiOnePayload { "title": "Bas", "body": "Fuubar", }, + Relationships: map[string]interface{}{ + "comments": &JsonApiRelationshipManyNode{ + Data: []*JsonApiNode{ + &JsonApiNode{ + Type: "comments", + Attributes: map[string]interface{}{ + "body": "Great post!", + }, + }, + &JsonApiNode{ + Type: "comments", + Attributes: map[string]interface{}{ + "body": "Needs some work!", + }, + }, + }, + }, + }, }, }, }, @@ -80,9 +147,5 @@ func samplePayload() *JsonApiOnePayload { json.NewEncoder(out).Encode(payload) - p := new(JsonApiOnePayload) - - json.NewDecoder(out).Decode(p) - - return p + return out } diff --git a/response_test.go b/response_test.go index c395d47..504026e 100644 --- a/response_test.go +++ b/response_test.go @@ -9,10 +9,16 @@ import ( "time" ) +type Comment struct { + Id int `jsonapi:"primary,comments"` + Body string `jsonapi:"attr,body"` +} + type Post struct { - Id int `jsonapi:"primary,posts"` - Title string `jsonapi:"attr,title"` - Body string `jsonapi:"attr,body"` + Id int `jsonapi:"primary,posts"` + Title string `jsonapi:"attr,title"` + Body string `jsonapi:"attr,body"` + Comments []*Comment `jsonapi:"relation,comments"` } type Blog struct {