Added the MarshalOnePayloadWithoutIncluded method for marshaling sing… (#34)

* Added the MarshalOnePayloadWithoutIncluded method for marshaling single objects and their relations without actually populating the "included" key with the full related object.

* Completed method description.

* Added a test to ensure that the library is capable of Unmarshmaling a payload where the One object in the payload had relationships but did not include them via "included"
This commit is contained in:
Aren Patel 2016-07-13 18:32:04 -07:00 committed by GitHub
parent 5005a0cfae
commit 0c87c2c473
3 changed files with 110 additions and 0 deletions

View File

@ -60,6 +60,23 @@ func TestUnmarshalSetsAttrs(t *testing.T) {
}
}
func TestUnmarshalRelationshipsWithoutIncluded(t *testing.T) {
data, _ := samplePayloadWithoutIncluded()
in := bytes.NewReader(data)
out := new(Post)
if err := UnmarshalPayload(in, out); err != nil {
t.Fatal(err)
}
// Verify each comment has at least an ID
for _, comment := range out.Comments {
if comment.Id == 0 {
t.Fatalf("The comment did not have an ID")
}
}
}
func TestUnmarshalRelationships(t *testing.T) {
out, err := unmarshalSamplePayload()
if err != nil {
@ -216,6 +233,41 @@ func unmarshalSamplePayload() (*Blog, error) {
return out, nil
}
func samplePayloadWithoutIncluded() (result []byte, err error) {
data := map[string]interface{}{
"data": map[string]interface{}{
"type": "posts",
"id": "1",
"attributes": map[string]interface{}{
"body": "Hello",
"title": "World",
},
"relationships": map[string]interface{}{
"comments": map[string]interface{}{
"data": []interface{}{
map[string]interface{}{
"type": "comments",
"id": "123",
},
map[string]interface{}{
"type": "comments",
"id": "456",
},
},
},
"latest_comment": map[string]interface{}{
"data": map[string]interface{}{
"type": "comments",
"id": "55555",
},
},
},
},
}
result, err = json.Marshal(data)
return
}
func samplePayload() io.Reader {
payload := &OnePayload{
Data: &Node{

View File

@ -36,6 +36,26 @@ func MarshalOnePayload(w io.Writer, model interface{}) error {
return nil
}
// MarshalOnePayloadWithoutIncluded writes a jsonapi response with one object,
// without the related records sideloaded into "included" array. If you want to
// serialzie the realtions into the "included" array see MarshalOnePayload.
//
// model interface{} should be a pointer to a struct.
func MarshalOnePayloadWithoutIncluded(w io.Writer, model interface{}) error {
included := make(map[string]*Node)
rootNode, err := visitModelNode(model, &included, true)
if err != nil {
return err
}
if err := json.NewEncoder(w).Encode(&OnePayload{Data: rootNode}); err != nil {
return err
}
return nil
}
// MarshalOne does the same as MarshalOnePayload except it just returns the payload
// and doesn't write out results.
// Useful is you use your JSON rendering library.

View File

@ -171,6 +171,44 @@ func TestNoRelations(t *testing.T) {
}
}
func TestMarshalOnePayloadWithoutIncluded(t *testing.T) {
data := &Post{
Id: 1,
BlogId: 2,
ClientId: "123e4567-e89b-12d3-a456-426655440000",
Title: "Foo",
Body: "Bar",
Comments: []*Comment{
&Comment{
Id: 20,
Body: "First",
},
&Comment{
Id: 21,
Body: "Hello World",
},
},
LatestComment: &Comment{
Id: 22,
Body: "Cool!",
},
}
out := bytes.NewBuffer(nil)
if err := MarshalOnePayloadWithoutIncluded(out, data); err != nil {
t.Fatal(err)
}
resp := new(OnePayload)
if err := json.NewDecoder(out).Decode(resp); err != nil {
t.Fatal(err)
}
if resp.Included != nil {
t.Fatalf("Encoding json response did not omit included")
}
}
func TestMarshalMany(t *testing.T) {
data := []interface{}{
&Blog{