Skip to content

Public Marshal API Simplification #90

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jun 29, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 7 additions & 64 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,18 +206,17 @@ UnmarshalPayload(in io.Reader, model interface{})

Visit [godoc](http://godoc.org/github.com/google/jsonapi#UnmarshalPayload)

#### `MarshalOnePayload`
#### `MarshalPayload`

```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
`included` array. This method encodes a response for a single record
only. If you want to serialize many records, see,
[MarshalManyPayload](#marshalmanypayload).
`included` array. This method encodes a response for either a single record or
many records.

##### Handler Example Code

Expand All @@ -235,63 +234,7 @@ func CreateBlog(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", jsonapi.MediaType)
w.WriteHeader(http.StatusCreated)

if err := jsonapi.MarshalOnePayload(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 {
if err := jsonapi.MarshalPayload(w, blog); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
Expand Down Expand Up @@ -329,7 +272,7 @@ func CreateBlogs(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", jsonapi.MediaType)
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)
}
}
Expand Down
2 changes: 1 addition & 1 deletion examples/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ func exerciseHandler() {
fixtureBlogCreate(3),
}
in = bytes.NewBuffer(nil)
jsonapi.MarshalManyPayload(in, blogs)
jsonapi.MarshalPayload(in, blogs)

req, _ = http.NewRequest(http.MethodPut, "/blogs", in)

Expand Down
8 changes: 4 additions & 4 deletions examples/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ func (h *ExampleHandler) createBlog(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusCreated)
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)
}
}
Expand All @@ -70,7 +70,7 @@ func (h *ExampleHandler) echoBlogs(w http.ResponseWriter, r *http.Request) {

w.WriteHeader(http.StatusOK)
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)
}
}
Expand All @@ -93,7 +93,7 @@ func (h *ExampleHandler) showBlog(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)

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)
}
}
Expand All @@ -108,7 +108,7 @@ func (h *ExampleHandler) listBlogs(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", jsonapi.MediaType)
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)
}
}
2 changes: 1 addition & 1 deletion examples/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func TestExampleHandler_put(t *testing.T) {
fixtureBlogCreate(3),
}
requestBody := bytes.NewBuffer(nil)
jsonapi.MarshalManyPayload(requestBody, blogs)
jsonapi.MarshalPayload(requestBody, blogs)

r, err := http.NewRequest(http.MethodPut, "/blogs", requestBody)
if err != nil {
Expand Down
13 changes: 13 additions & 0 deletions node.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ package jsonapi

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
// resource (Node) was included as an {} in the "data" key
type OnePayload struct {
Expand All @@ -11,6 +16,10 @@ type OnePayload struct {
Meta *Meta `json:"meta,omitempty"`
}

func (p *OnePayload) clearIncluded() {
p.Included = []*Node{}
}

// ManyPayload is used to represent a generic JSON API payload where many
// resources (Nodes) were included in an [] in the "data" key
type ManyPayload struct {
Expand All @@ -20,6 +29,10 @@ type ManyPayload struct {
Meta *Meta `json:"meta,omitempty"`
}

func (p *ManyPayload) clearIncluded() {
p.Included = []*Node{}
}

// Node is used to represent a generic JSON API Resource
type Node struct {
Type string `json:"type"`
Expand Down
2 changes: 1 addition & 1 deletion request.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ var (
// w.Header().Set("Content-Type", jsonapi.MediaType)
// 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)
// }
// }
Expand Down
2 changes: 1 addition & 1 deletion request_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -931,7 +931,7 @@ func samplePayloadWithSideloaded() io.Reader {
testModel := testModel()

out := bytes.NewBuffer(nil)
MarshalOnePayload(out, testModel)
MarshalPayload(out, testModel)

return out
}
Expand Down
Loading