Public Marshal API Simplification (#90)

* Used to have 6 functions: MarshalOnePayload, MarshalOnePayloadWithoutIncluded, MarshalOne, MarshalManyPayload, MarshalManyPayloadWithoutIncluded, MarshalMany - now there are only 3: MarshalPayload, MarshalPayloadWithoutIncluded, Marshal. This simplifies the public API; will be easier to explain and document while still providing the existing support for struct ptrs (&Blog{}) and slices of struct ptrs ([]*Blog{}).

* Correcting all code occurrences leftover.

* Updating README to reflect Marshal API changes.

* Omit the mention of One vs Many
This commit is contained in:
Aren Patel 2017-06-28 17:30:09 -07:00 committed by GitHub
parent ebb7923313
commit cf83b97b3d
10 changed files with 172 additions and 216 deletions

View File

@ -206,18 +206,17 @@ UnmarshalPayload(in io.Reader, model interface{})
Visit [godoc](http://godoc.org/github.com/google/jsonapi#UnmarshalPayload) Visit [godoc](http://godoc.org/github.com/google/jsonapi#UnmarshalPayload)
#### `MarshalOnePayload` #### `MarshalPayload`
```go ```go
MarshalOnePayload(w io.Writer, model interface{}) error MarshalPayload(w io.Writer, models interface{}) error
``` ```
Visit [godoc](http://godoc.org/github.com/google/jsonapi#MarshalOnePayload) Visit [godoc](http://godoc.org/github.com/google/jsonapi#MarshalPayload)
Writes a JSON API response, with related records sideloaded, into an Writes a JSON API response, with related records sideloaded, into an
`included` array. This method encodes a response for a single record `included` array. This method encodes a response for either a single record or
only. If you want to serialize many records, see, many records.
[MarshalManyPayload](#marshalmanypayload).
##### Handler Example Code ##### Handler Example Code
@ -235,63 +234,7 @@ func CreateBlog(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", jsonapi.MediaType) w.Header().Set("Content-Type", jsonapi.MediaType)
w.WriteHeader(http.StatusCreated) w.WriteHeader(http.StatusCreated)
if err := jsonapi.MarshalOnePayload(w, blog); err != nil { if err := jsonapi.MarshalPayload(w, blog); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
```
### List Records Example
#### `MarshalManyPayload`
```go
MarshalManyPayload(w io.Writer, models []interface{}) error
```
Visit [godoc](http://godoc.org/github.com/google/jsonapi#MarshalManyPayload)
Takes an `io.Writer` and an slice of `interface{}`. Note, if you have a
type safe array of your structs, like,
```go
var blogs []*Blog
```
you will need to iterate over the slice of `Blog` pointers and append
them to an interface array, like,
```go
blogInterface := make([]interface{}, len(blogs))
for i, blog := range blogs {
blogInterface[i] = blog
}
```
Alternatively, you can insert your `Blog`s into a slice of `interface{}`
the first time. For example when you fetch the `Blog`s from the db
`append` them to an `[]interface{}` rather than a `[]*Blog`. So your
method signature to reach into your data store may look something like
this,
```go
func FetchBlogs() ([]interface{}, error)
```
##### Handler Example Code
```go
func ListBlogs(w http.ResponseWriter, r *http.Request) {
// ...fetch your blogs, filter, offset, limit, etc...
// but, for now
blogs := testBlogsForList()
w.Header().Set("Content-Type", jsonapi.MediaType)
w.WriteHeader(http.StatusOK)
if err := jsonapi.MarshalManyPayload(w, blogs); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
} }
} }
@ -329,7 +272,7 @@ func CreateBlogs(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", jsonapi.MediaType) w.Header().Set("Content-Type", jsonapi.MediaType)
w.WriteHeader(http.StatusCreated) w.WriteHeader(http.StatusCreated)
if err := jsonapi.MarshalManyPayload(w, blogs); err != nil { if err := jsonapi.MarshalPayload(w, blogs); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
} }
} }

View File

@ -103,7 +103,7 @@ func exerciseHandler() {
fixtureBlogCreate(3), fixtureBlogCreate(3),
} }
in = bytes.NewBuffer(nil) in = bytes.NewBuffer(nil)
jsonapi.MarshalManyPayload(in, blogs) jsonapi.MarshalPayload(in, blogs)
req, _ = http.NewRequest(http.MethodPut, "/blogs", in) req, _ = http.NewRequest(http.MethodPut, "/blogs", in)

View File

@ -56,7 +56,7 @@ func (h *ExampleHandler) createBlog(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusCreated) w.WriteHeader(http.StatusCreated)
w.Header().Set(headerContentType, jsonapi.MediaType) w.Header().Set(headerContentType, jsonapi.MediaType)
if err := jsonapiRuntime.MarshalOnePayload(w, blog); err != nil { if err := jsonapiRuntime.MarshalPayload(w, blog); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
} }
} }
@ -70,7 +70,7 @@ func (h *ExampleHandler) echoBlogs(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
w.Header().Set(headerContentType, jsonapi.MediaType) w.Header().Set(headerContentType, jsonapi.MediaType)
if err := jsonapiRuntime.MarshalManyPayload(w, blogs); err != nil { if err := jsonapiRuntime.MarshalPayload(w, blogs); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
} }
} }
@ -93,7 +93,7 @@ func (h *ExampleHandler) showBlog(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
w.Header().Set(headerContentType, jsonapi.MediaType) w.Header().Set(headerContentType, jsonapi.MediaType)
if err := jsonapiRuntime.MarshalOnePayload(w, blog); err != nil { if err := jsonapiRuntime.MarshalPayload(w, blog); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
} }
} }
@ -108,7 +108,7 @@ func (h *ExampleHandler) listBlogs(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", jsonapi.MediaType) w.Header().Set("Content-Type", jsonapi.MediaType)
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
if err := jsonapiRuntime.MarshalManyPayload(w, blogs); err != nil { if err := jsonapiRuntime.MarshalPayload(w, blogs); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
} }
} }

View File

@ -36,7 +36,7 @@ func TestExampleHandler_put(t *testing.T) {
fixtureBlogCreate(3), fixtureBlogCreate(3),
} }
requestBody := bytes.NewBuffer(nil) requestBody := bytes.NewBuffer(nil)
jsonapi.MarshalManyPayload(requestBody, blogs) jsonapi.MarshalPayload(requestBody, blogs)
r, err := http.NewRequest(http.MethodPut, "/blogs", requestBody) r, err := http.NewRequest(http.MethodPut, "/blogs", requestBody)
if err != nil { if err != nil {

13
node.go
View File

@ -2,6 +2,11 @@ package jsonapi
import "fmt" import "fmt"
// Payloader is used to encapsulate the One and Many payload types
type Payloader interface {
clearIncluded()
}
// OnePayload is used to represent a generic JSON API payload where a single // OnePayload is used to represent a generic JSON API payload where a single
// resource (Node) was included as an {} in the "data" key // resource (Node) was included as an {} in the "data" key
type OnePayload struct { type OnePayload struct {
@ -11,6 +16,10 @@ type OnePayload struct {
Meta *Meta `json:"meta,omitempty"` Meta *Meta `json:"meta,omitempty"`
} }
func (p *OnePayload) clearIncluded() {
p.Included = []*Node{}
}
// ManyPayload is used to represent a generic JSON API payload where many // ManyPayload is used to represent a generic JSON API payload where many
// resources (Nodes) were included in an [] in the "data" key // resources (Nodes) were included in an [] in the "data" key
type ManyPayload struct { type ManyPayload struct {
@ -20,6 +29,10 @@ type ManyPayload struct {
Meta *Meta `json:"meta,omitempty"` Meta *Meta `json:"meta,omitempty"`
} }
func (p *ManyPayload) clearIncluded() {
p.Included = []*Node{}
}
// Node is used to represent a generic JSON API Resource // Node is used to represent a generic JSON API Resource
type Node struct { type Node struct {
Type string `json:"type"` Type string `json:"type"`

View File

@ -58,7 +58,7 @@ var (
// w.Header().Set("Content-Type", jsonapi.MediaType) // w.Header().Set("Content-Type", jsonapi.MediaType)
// w.WriteHeader(201) // w.WriteHeader(201)
// //
// if err := jsonapi.MarshalOnePayload(w, blog); err != nil { // if err := jsonapi.MarshalPayload(w, blog); err != nil {
// http.Error(w, err.Error(), 500) // http.Error(w, err.Error(), 500)
// } // }
// } // }

View File

@ -931,7 +931,7 @@ func samplePayloadWithSideloaded() io.Reader {
testModel := testModel() testModel := testModel()
out := bytes.NewBuffer(nil) out := bytes.NewBuffer(nil)
MarshalOnePayload(out, testModel) MarshalPayload(out, testModel)
return out return out
} }

View File

@ -23,18 +23,47 @@ var (
// be a slice of *Structs; MarshalMany will return this error when its // be a slice of *Structs; MarshalMany will return this error when its
// interface{} argument is invalid. // interface{} argument is invalid.
ErrExpectedSlice = errors.New("models should be a slice of struct pointers") ErrExpectedSlice = errors.New("models should be a slice of struct pointers")
// ErrUnexpectedType is returned when marshalling an interface; the interface
// had to be a pointer or a slice; otherwise this error is returned.
ErrUnexpectedType = errors.New("models should be a struct pointer or slice of struct pointers")
) )
// MarshalOnePayload writes a jsonapi response with one, with related records // MarshalPayload writes a jsonapi response for one or many records. The
// sideloaded, into "included" array. This method encodes a response for a // related records are sideloaded into the "included" array. If this method is
// single record only. Hence, data will be a single record rather than an array // given a struct pointer as an argument it will serialize in the form
// of records. If you want to serialize many records, see, MarshalManyPayload. // "data": {...}. If this method is given a slice of pointers, this method will
// serialize in the form "data": [...]
// //
// See UnmarshalPayload for usage example. // One Example: you could pass it, w, your http.ResponseWriter, and, models, a
// ptr to a Blog to be written to the response body:
// //
// model interface{} should be a pointer to a struct. // func ShowBlog(w http.ResponseWriter, r *http.Request) {
func MarshalOnePayload(w io.Writer, model interface{}) error { // blog := &Blog{}
payload, err := MarshalOne(model) //
// w.Header().Set("Content-Type", jsonapi.MediaType)
// w.WriteHeader(http.StatusOK)
//
// if err := jsonapi.MarshalPayload(w, blog); err != nil {
// http.Error(w, err.Error(), http.StatusInternalServerError)
// }
// }
//
// Many Example: you could pass it, w, your http.ResponseWriter, and, models, a
// slice of Blog struct instance pointers to be written to the response body:
//
// func ListBlogs(w http.ResponseWriter, r *http.Request) {
// blogs := []*Blog{}
//
// w.Header().Set("Content-Type", jsonapi.MediaType)
// w.WriteHeader(http.StatusOK)
//
// if err := jsonapi.MarshalPayload(w, blogs); err != nil {
// http.Error(w, err.Error(), http.StatusInternalServerError)
// }
// }
//
func MarshalPayload(w io.Writer, models interface{}) error {
payload, err := Marshal(models)
if err != nil { if err != nil {
return err return err
} }
@ -42,34 +71,55 @@ func MarshalOnePayload(w io.Writer, model interface{}) error {
if err := json.NewEncoder(w).Encode(payload); err != nil { if err := json.NewEncoder(w).Encode(payload); err != nil {
return err return err
} }
return nil return nil
} }
// MarshalOnePayloadWithoutIncluded writes a jsonapi response with one object, // Marshal does the same as MarshalPayload except it just returns the payload
// without the related records sideloaded into "included" array. If you want to // and doesn't write out results. Useful if you use your own JSON rendering
// serialize the relations into the "included" array see MarshalOnePayload. // library.
// func Marshal(models interface{}) (Payloader, error) {
// model interface{} should be a pointer to a struct. switch vals := reflect.ValueOf(models); vals.Kind() {
func MarshalOnePayloadWithoutIncluded(w io.Writer, model interface{}) error { case reflect.Slice:
included := make(map[string]*Node) m, err := convertToSliceInterface(&models)
if err != nil {
return nil, err
}
return marshalMany(m)
case reflect.Ptr:
// Check that the pointer was to a struct
if reflect.Indirect(vals).Kind() != reflect.Struct {
return nil, ErrUnexpectedType
}
return marshalOne(models)
default:
return nil, ErrUnexpectedType
}
}
rootNode, err := visitModelNode(model, &included, true) // MarshalPayloadWithoutIncluded writes a jsonapi response with one or many
// records, without the related records sideloaded into "included" array.
// If you want to serialize the relations into the "included" array see
// MarshalPayload.
//
// models interface{} should be either a struct pointer or a slice of struct
// pointers.
func MarshalPayloadWithoutIncluded(w io.Writer, model interface{}) error {
payload, err := Marshal(model)
if err != nil { if err != nil {
return err return err
} }
payload.clearIncluded()
if err := json.NewEncoder(w).Encode(&OnePayload{Data: rootNode}); err != nil { if err := json.NewEncoder(w).Encode(payload); err != nil {
return err return err
} }
return nil return nil
} }
// MarshalOne does the same as MarshalOnePayload except it just returns the // 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 // payload and doesn't write out results. Useful is you use your JSON rendering
// library. // library.
func MarshalOne(model interface{}) (*OnePayload, error) { func marshalOne(model interface{}) (*OnePayload, error) {
included := make(map[string]*Node) included := make(map[string]*Node)
rootNode, err := visitModelNode(model, &included, true) rootNode, err := visitModelNode(model, &included, true)
@ -83,78 +133,10 @@ func MarshalOne(model interface{}) (*OnePayload, error) {
return payload, nil return payload, nil
} }
// MarshalManyPayloadWithoutIncluded writes a jsonapi response with many records, // marshalMany does the same as MarshalManyPayload except it just returns the
// without the related records sideloaded into "included" array. If you want to
// serialize the relations into the "included" array see MarshalManyPayload.
//
// models interface{} should be a slice of struct pointers.
func MarshalManyPayloadWithoutIncluded(w io.Writer, models interface{}) error {
m, err := convertToSliceInterface(&models)
if err != nil {
return err
}
payload, err := MarshalMany(m)
if err != nil {
return err
}
// Empty the included
payload.Included = []*Node{}
if err := json.NewEncoder(w).Encode(payload); err != nil {
return err
}
return nil
}
// MarshalManyPayload writes a jsonapi response with many records, with related
// records sideloaded, into "included" array. This method encodes a response for
// a slice of records, hence data will be an array of records rather than a
// single record. To serialize a single record, see MarshalOnePayload
//
// For example you could pass it, w, your http.ResponseWriter, and, models, a
// slice of Blog struct instance pointers as interface{}'s to write to the
// response,
//
// func ListBlogs(w http.ResponseWriter, r *http.Request) {
// // ... fetch your blogs and filter, offset, limit, etc ...
//
// blogs := testBlogsForList()
//
// w.Header().Set("Content-Type", jsonapi.MediaType)
// w.WriteHeader(http.StatusOK)
//
// if err := jsonapi.MarshalManyPayload(w, blogs); err != nil {
// http.Error(w, err.Error(), http.StatusInternalServerError)
// }
// }
//
//
// Visit https://github.com/google/jsonapi#list for more info.
//
// models interface{} should be a slice of struct pointers.
func MarshalManyPayload(w io.Writer, models interface{}) error {
m, err := convertToSliceInterface(&models)
if err != nil {
return err
}
payload, err := MarshalMany(m)
if err != nil {
return err
}
if err := json.NewEncoder(w).Encode(payload); err != nil {
return err
}
return nil
}
// MarshalMany does the same as MarshalManyPayload except it just returns the
// payload and doesn't write out results. Useful is you use your JSON rendering // payload and doesn't write out results. Useful is you use your JSON rendering
// library. // library.
func MarshalMany(models []interface{}) (*ManyPayload, error) { func marshalMany(models []interface{}) (*ManyPayload, error) {
payload := &ManyPayload{ payload := &ManyPayload{
Data: []*Node{}, Data: []*Node{},
} }
@ -173,16 +155,18 @@ func MarshalMany(models []interface{}) (*ManyPayload, error) {
} }
// MarshalOnePayloadEmbedded - This method not meant to for use in // MarshalOnePayloadEmbedded - This method not meant to for use in
// implementation code, although feel free. The purpose of this method is for // implementation code, although feel free. The purpose of this
// use in tests. In most cases, your request payloads for create will be // method is for use in tests. In most cases, your request
// embedded rather than sideloaded for related records. This method will // payloads for create will be embedded rather than sideloaded for
// serialize a single struct pointer into an embedded json response. In other // related records. This method will serialize a single struct
// words, there will be no, "included", array in the json all relationships will // pointer into an embedded json response. In other words, there
// will be no, "included", array in the json all relationships will
// be serailized inline in the data. // be serailized inline in the data.
// //
// However, in tests, you may want to construct payloads to post to create // However, in tests, you may want to construct payloads to post
// methods that are embedded to most closely resemble the payloads that will be // to create methods that are embedded to most closely resemble
// produced by the client. This is what this method is intended for. // the payloads that will be produced by the client. This is what
// this method is intended for.
// //
// model interface{} should be a pointer to a struct. // model interface{} should be a pointer to a struct.
func MarshalOnePayloadEmbedded(w io.Writer, model interface{}) error { func MarshalOnePayloadEmbedded(w io.Writer, model interface{}) error {

View File

@ -9,12 +9,40 @@ import (
"time" "time"
) )
func TestMarshall_attrStringSlice(t *testing.T) { func TestMarshalPayload(t *testing.T) {
book := &Book{ID: 1}
books := []*Book{book, &Book{ID: 2}}
var jsonData map[string]interface{}
// One
out1 := bytes.NewBuffer(nil)
MarshalPayload(out1, book)
if err := json.Unmarshal(out1.Bytes(), &jsonData); err != nil {
t.Fatal(err)
}
if _, ok := jsonData["data"].(map[string]interface{}); !ok {
t.Fatalf("data key did not contain an Hash/Dict/Map")
}
// Many
out2 := bytes.NewBuffer(nil)
MarshalPayload(out2, books)
if err := json.Unmarshal(out2.Bytes(), &jsonData); err != nil {
t.Fatal(err)
}
if _, ok := jsonData["data"].([]interface{}); !ok {
t.Fatalf("data key did not contain an Array")
}
}
func TestMarshal_attrStringSlice(t *testing.T) {
tags := []string{"fiction", "sale"} tags := []string{"fiction", "sale"}
b := &Book{ID: 1, Tags: tags} b := &Book{ID: 1, Tags: tags}
out := bytes.NewBuffer(nil) out := bytes.NewBuffer(nil)
if err := MarshalOnePayload(out, b); err != nil { if err := MarshalPayload(out, b); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -49,7 +77,7 @@ func TestWithoutOmitsEmptyAnnotationOnRelation(t *testing.T) {
blog := &Blog{} blog := &Blog{}
out := bytes.NewBuffer(nil) out := bytes.NewBuffer(nil)
if err := MarshalOnePayload(out, blog); err != nil { if err := MarshalPayload(out, blog); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -109,7 +137,7 @@ func TestWithOmitsEmptyAnnotationOnRelation(t *testing.T) {
blog := &BlogOptionalPosts{ID: 999} blog := &BlogOptionalPosts{ID: 999}
out := bytes.NewBuffer(nil) out := bytes.NewBuffer(nil)
if err := MarshalOnePayload(out, blog); err != nil { if err := MarshalPayload(out, blog); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -141,7 +169,7 @@ func TestWithOmitsEmptyAnnotationOnRelation_MixedData(t *testing.T) {
} }
out := bytes.NewBuffer(nil) out := bytes.NewBuffer(nil)
if err := MarshalOnePayload(out, blog); err != nil { if err := MarshalPayload(out, blog); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -175,7 +203,7 @@ func TestMarshalIDPtr(t *testing.T) {
} }
out := bytes.NewBuffer(nil) out := bytes.NewBuffer(nil)
if err := MarshalOnePayload(out, car); err != nil { if err := MarshalPayload(out, car); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -204,7 +232,7 @@ func TestMarshalOnePayload_omitIDString(t *testing.T) {
foo := &Foo{Title: "Foo"} foo := &Foo{Title: "Foo"}
out := bytes.NewBuffer(nil) out := bytes.NewBuffer(nil)
if err := MarshalOnePayload(out, foo); err != nil { if err := MarshalPayload(out, foo); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -230,7 +258,7 @@ func TestMarshall_invalidIDType(t *testing.T) {
o := &badIDStruct{ID: &id} o := &badIDStruct{ID: &id}
out := bytes.NewBuffer(nil) out := bytes.NewBuffer(nil)
if err := MarshalOnePayload(out, o); err != ErrBadJSONAPIID { if err := MarshalPayload(out, o); err != ErrBadJSONAPIID {
t.Fatalf( t.Fatalf(
"Was expecting a `%s` error, got `%s`", ErrBadJSONAPIID, err, "Was expecting a `%s` error, got `%s`", ErrBadJSONAPIID, err,
) )
@ -244,7 +272,7 @@ func TestOmitsEmptyAnnotation(t *testing.T) {
} }
out := bytes.NewBuffer(nil) out := bytes.NewBuffer(nil)
if err := MarshalOnePayload(out, book); err != nil { if err := MarshalPayload(out, book); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -281,7 +309,7 @@ func TestHasPrimaryAnnotation(t *testing.T) {
} }
out := bytes.NewBuffer(nil) out := bytes.NewBuffer(nil)
if err := MarshalOnePayload(out, testModel); err != nil { if err := MarshalPayload(out, testModel); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -310,7 +338,7 @@ func TestSupportsAttributes(t *testing.T) {
} }
out := bytes.NewBuffer(nil) out := bytes.NewBuffer(nil)
if err := MarshalOnePayload(out, testModel); err != nil { if err := MarshalPayload(out, testModel); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -338,7 +366,7 @@ func TestOmitsZeroTimes(t *testing.T) {
} }
out := bytes.NewBuffer(nil) out := bytes.NewBuffer(nil)
if err := MarshalOnePayload(out, testModel); err != nil { if err := MarshalPayload(out, testModel); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -365,7 +393,7 @@ func TestMarshalISO8601Time(t *testing.T) {
} }
out := bytes.NewBuffer(nil) out := bytes.NewBuffer(nil)
if err := MarshalOnePayload(out, testModel); err != nil { if err := MarshalPayload(out, testModel); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -393,7 +421,7 @@ func TestMarshalISO8601TimePointer(t *testing.T) {
} }
out := bytes.NewBuffer(nil) out := bytes.NewBuffer(nil)
if err := MarshalOnePayload(out, testModel); err != nil { if err := MarshalPayload(out, testModel); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -421,7 +449,7 @@ func TestSupportsLinkable(t *testing.T) {
} }
out := bytes.NewBuffer(nil) out := bytes.NewBuffer(nil)
if err := MarshalOnePayload(out, testModel); err != nil { if err := MarshalPayload(out, testModel); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -490,7 +518,7 @@ func TestInvalidLinkable(t *testing.T) {
} }
out := bytes.NewBuffer(nil) out := bytes.NewBuffer(nil)
if err := MarshalOnePayload(out, testModel); err == nil { if err := MarshalPayload(out, testModel); err == nil {
t.Fatal("Was expecting an error") t.Fatal("Was expecting an error")
} }
} }
@ -503,7 +531,7 @@ func TestSupportsMetable(t *testing.T) {
} }
out := bytes.NewBuffer(nil) out := bytes.NewBuffer(nil)
if err := MarshalOnePayload(out, testModel); err != nil { if err := MarshalPayload(out, testModel); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -527,7 +555,7 @@ func TestRelations(t *testing.T) {
testModel := testBlog() testModel := testBlog()
out := bytes.NewBuffer(nil) out := bytes.NewBuffer(nil)
if err := MarshalOnePayload(out, testModel); err != nil { if err := MarshalPayload(out, testModel); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -573,7 +601,7 @@ func TestNoRelations(t *testing.T) {
testModel := &Blog{ID: 1, Title: "Title 1", CreatedAt: time.Now()} testModel := &Blog{ID: 1, Title: "Title 1", CreatedAt: time.Now()}
out := bytes.NewBuffer(nil) out := bytes.NewBuffer(nil)
if err := MarshalOnePayload(out, testModel); err != nil { if err := MarshalPayload(out, testModel); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -587,7 +615,7 @@ func TestNoRelations(t *testing.T) {
} }
} }
func TestMarshalOnePayloadWithoutIncluded(t *testing.T) { func TestMarshalPayloadWithoutIncluded(t *testing.T) {
data := &Post{ data := &Post{
ID: 1, ID: 1,
BlogID: 2, BlogID: 2,
@ -611,7 +639,7 @@ func TestMarshalOnePayloadWithoutIncluded(t *testing.T) {
} }
out := bytes.NewBuffer(nil) out := bytes.NewBuffer(nil)
if err := MarshalOnePayloadWithoutIncluded(out, data); err != nil { if err := MarshalPayloadWithoutIncluded(out, data); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -625,7 +653,7 @@ func TestMarshalOnePayloadWithoutIncluded(t *testing.T) {
} }
} }
func TestMarshalMany(t *testing.T) { func TestMarshalPayload_many(t *testing.T) {
data := []interface{}{ data := []interface{}{
&Blog{ &Blog{
ID: 5, ID: 5,
@ -674,7 +702,7 @@ func TestMarshalMany(t *testing.T) {
} }
out := bytes.NewBuffer(nil) out := bytes.NewBuffer(nil)
if err := MarshalManyPayload(out, data); err != nil { if err := MarshalPayload(out, data); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -697,7 +725,7 @@ func TestMarshalMany_WithSliceOfStructPointers(t *testing.T) {
} }
out := bytes.NewBuffer(nil) out := bytes.NewBuffer(nil)
if err := MarshalManyPayload(out, data); err != nil { if err := MarshalPayload(out, data); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -720,7 +748,7 @@ func TestMarshalManyWithoutIncluded(t *testing.T) {
} }
out := bytes.NewBuffer(nil) out := bytes.NewBuffer(nil)
if err := MarshalManyPayloadWithoutIncluded(out, data); err != nil { if err := MarshalPayloadWithoutIncluded(out, data); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -752,11 +780,11 @@ func TestMarshalMany_SliceOfInterfaceAndSliceOfStructsSameJSON(t *testing.T) {
// Perform Marshals // Perform Marshals
structsOut := new(bytes.Buffer) structsOut := new(bytes.Buffer)
if err := MarshalManyPayload(structsOut, structs); err != nil { if err := MarshalPayload(structsOut, structs); err != nil {
t.Fatal(err) t.Fatal(err)
} }
interfacesOut := new(bytes.Buffer) interfacesOut := new(bytes.Buffer)
if err := MarshalManyPayload(interfacesOut, interfaces); err != nil { if err := MarshalPayload(interfacesOut, interfaces); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -776,15 +804,15 @@ func TestMarshalMany_SliceOfInterfaceAndSliceOfStructsSameJSON(t *testing.T) {
} }
} }
func TestMarshalMany_InvalidIntefaceArgument(t *testing.T) { func TestMarshal_InvalidIntefaceArgument(t *testing.T) {
out := new(bytes.Buffer) out := new(bytes.Buffer)
if err := MarshalManyPayload(out, true); err != ErrExpectedSlice { if err := MarshalPayload(out, true); err != ErrUnexpectedType {
t.Fatal("Was expecting an error") t.Fatal("Was expecting an error")
} }
if err := MarshalManyPayload(out, 25); err != ErrExpectedSlice { if err := MarshalPayload(out, 25); err != ErrUnexpectedType {
t.Fatal("Was expecting an error") t.Fatal("Was expecting an error")
} }
if err := MarshalManyPayload(out, Book{}); err != ErrExpectedSlice { if err := MarshalPayload(out, Book{}); err != ErrUnexpectedType {
t.Fatal("Was expecting an error") t.Fatal("Was expecting an error")
} }
} }

View File

@ -60,21 +60,9 @@ func (r *Runtime) UnmarshalManyPayload(reader io.Reader, kind reflect.Type) (ele
return return
} }
func (r *Runtime) MarshalOnePayload(w io.Writer, model interface{}) error { func (r *Runtime) MarshalPayload(w io.Writer, model interface{}) error {
return r.instrumentCall(MarshalStart, MarshalStop, func() error { return r.instrumentCall(MarshalStart, MarshalStop, func() error {
return MarshalOnePayload(w, model) return MarshalPayload(w, model)
})
}
func (r *Runtime) MarshalManyPayload(w io.Writer, models interface{}) error {
return r.instrumentCall(MarshalStart, MarshalStop, func() error {
return MarshalManyPayload(w, models)
})
}
func (r *Runtime) MarshalOnePayloadEmbedded(w io.Writer, model interface{}) error {
return r.instrumentCall(MarshalStart, MarshalStop, func() error {
return MarshalOnePayloadEmbedded(w, model)
}) })
} }