Skip to content

Commit cf83b97

Browse files
authored
Public Marshal API Simplification (google#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
1 parent ebb7923 commit cf83b97

10 files changed

+172
-216
lines changed

README.md

+7-64
Original file line numberDiff line numberDiff line change
@@ -206,18 +206,17 @@ UnmarshalPayload(in io.Reader, model interface{})
206206

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

209-
#### `MarshalOnePayload`
209+
#### `MarshalPayload`
210210

211211
```go
212-
MarshalOnePayload(w io.Writer, model interface{}) error
212+
MarshalPayload(w io.Writer, models interface{}) error
213213
```
214214

215-
Visit [godoc](http://godoc.org/github.com/google/jsonapi#MarshalOnePayload)
215+
Visit [godoc](http://godoc.org/github.com/google/jsonapi#MarshalPayload)
216216

217217
Writes a JSON API response, with related records sideloaded, into an
218-
`included` array. This method encodes a response for a single record
219-
only. If you want to serialize many records, see,
220-
[MarshalManyPayload](#marshalmanypayload).
218+
`included` array. This method encodes a response for either a single record or
219+
many records.
221220

222221
##### Handler Example Code
223222

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

238-
if err := jsonapi.MarshalOnePayload(w, blog); err != nil {
239-
http.Error(w, err.Error(), http.StatusInternalServerError)
240-
}
241-
}
242-
```
243-
244-
### List Records Example
245-
246-
#### `MarshalManyPayload`
247-
248-
```go
249-
MarshalManyPayload(w io.Writer, models []interface{}) error
250-
```
251-
252-
Visit [godoc](http://godoc.org/github.com/google/jsonapi#MarshalManyPayload)
253-
254-
Takes an `io.Writer` and an slice of `interface{}`. Note, if you have a
255-
type safe array of your structs, like,
256-
257-
```go
258-
var blogs []*Blog
259-
```
260-
261-
you will need to iterate over the slice of `Blog` pointers and append
262-
them to an interface array, like,
263-
264-
```go
265-
blogInterface := make([]interface{}, len(blogs))
266-
267-
for i, blog := range blogs {
268-
blogInterface[i] = blog
269-
}
270-
```
271-
272-
Alternatively, you can insert your `Blog`s into a slice of `interface{}`
273-
the first time. For example when you fetch the `Blog`s from the db
274-
`append` them to an `[]interface{}` rather than a `[]*Blog`. So your
275-
method signature to reach into your data store may look something like
276-
this,
277-
278-
```go
279-
func FetchBlogs() ([]interface{}, error)
280-
```
281-
282-
##### Handler Example Code
283-
284-
```go
285-
func ListBlogs(w http.ResponseWriter, r *http.Request) {
286-
// ...fetch your blogs, filter, offset, limit, etc...
287-
288-
// but, for now
289-
blogs := testBlogsForList()
290-
291-
w.Header().Set("Content-Type", jsonapi.MediaType)
292-
w.WriteHeader(http.StatusOK)
293-
294-
if err := jsonapi.MarshalManyPayload(w, blogs); err != nil {
237+
if err := jsonapi.MarshalPayload(w, blog); err != nil {
295238
http.Error(w, err.Error(), http.StatusInternalServerError)
296239
}
297240
}
@@ -329,7 +272,7 @@ func CreateBlogs(w http.ResponseWriter, r *http.Request) {
329272
w.Header().Set("Content-Type", jsonapi.MediaType)
330273
w.WriteHeader(http.StatusCreated)
331274

332-
if err := jsonapi.MarshalManyPayload(w, blogs); err != nil {
275+
if err := jsonapi.MarshalPayload(w, blogs); err != nil {
333276
http.Error(w, err.Error(), http.StatusInternalServerError)
334277
}
335278
}

examples/app.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ func exerciseHandler() {
103103
fixtureBlogCreate(3),
104104
}
105105
in = bytes.NewBuffer(nil)
106-
jsonapi.MarshalManyPayload(in, blogs)
106+
jsonapi.MarshalPayload(in, blogs)
107107

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

examples/handler.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ func (h *ExampleHandler) createBlog(w http.ResponseWriter, r *http.Request) {
5656
w.WriteHeader(http.StatusCreated)
5757
w.Header().Set(headerContentType, jsonapi.MediaType)
5858

59-
if err := jsonapiRuntime.MarshalOnePayload(w, blog); err != nil {
59+
if err := jsonapiRuntime.MarshalPayload(w, blog); err != nil {
6060
http.Error(w, err.Error(), http.StatusInternalServerError)
6161
}
6262
}
@@ -70,7 +70,7 @@ func (h *ExampleHandler) echoBlogs(w http.ResponseWriter, r *http.Request) {
7070

7171
w.WriteHeader(http.StatusOK)
7272
w.Header().Set(headerContentType, jsonapi.MediaType)
73-
if err := jsonapiRuntime.MarshalManyPayload(w, blogs); err != nil {
73+
if err := jsonapiRuntime.MarshalPayload(w, blogs); err != nil {
7474
http.Error(w, err.Error(), http.StatusInternalServerError)
7575
}
7676
}
@@ -93,7 +93,7 @@ func (h *ExampleHandler) showBlog(w http.ResponseWriter, r *http.Request) {
9393
w.WriteHeader(http.StatusOK)
9494

9595
w.Header().Set(headerContentType, jsonapi.MediaType)
96-
if err := jsonapiRuntime.MarshalOnePayload(w, blog); err != nil {
96+
if err := jsonapiRuntime.MarshalPayload(w, blog); err != nil {
9797
http.Error(w, err.Error(), http.StatusInternalServerError)
9898
}
9999
}
@@ -108,7 +108,7 @@ func (h *ExampleHandler) listBlogs(w http.ResponseWriter, r *http.Request) {
108108
w.Header().Set("Content-Type", jsonapi.MediaType)
109109
w.WriteHeader(http.StatusOK)
110110

111-
if err := jsonapiRuntime.MarshalManyPayload(w, blogs); err != nil {
111+
if err := jsonapiRuntime.MarshalPayload(w, blogs); err != nil {
112112
http.Error(w, err.Error(), http.StatusInternalServerError)
113113
}
114114
}

examples/handler_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ func TestExampleHandler_put(t *testing.T) {
3636
fixtureBlogCreate(3),
3737
}
3838
requestBody := bytes.NewBuffer(nil)
39-
jsonapi.MarshalManyPayload(requestBody, blogs)
39+
jsonapi.MarshalPayload(requestBody, blogs)
4040

4141
r, err := http.NewRequest(http.MethodPut, "/blogs", requestBody)
4242
if err != nil {

node.go

+13
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@ package jsonapi
22

33
import "fmt"
44

5+
// Payloader is used to encapsulate the One and Many payload types
6+
type Payloader interface {
7+
clearIncluded()
8+
}
9+
510
// OnePayload is used to represent a generic JSON API payload where a single
611
// resource (Node) was included as an {} in the "data" key
712
type OnePayload struct {
@@ -11,6 +16,10 @@ type OnePayload struct {
1116
Meta *Meta `json:"meta,omitempty"`
1217
}
1318

19+
func (p *OnePayload) clearIncluded() {
20+
p.Included = []*Node{}
21+
}
22+
1423
// ManyPayload is used to represent a generic JSON API payload where many
1524
// resources (Nodes) were included in an [] in the "data" key
1625
type ManyPayload struct {
@@ -20,6 +29,10 @@ type ManyPayload struct {
2029
Meta *Meta `json:"meta,omitempty"`
2130
}
2231

32+
func (p *ManyPayload) clearIncluded() {
33+
p.Included = []*Node{}
34+
}
35+
2336
// Node is used to represent a generic JSON API Resource
2437
type Node struct {
2538
Type string `json:"type"`

request.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ var (
5858
// w.Header().Set("Content-Type", jsonapi.MediaType)
5959
// w.WriteHeader(201)
6060
//
61-
// if err := jsonapi.MarshalOnePayload(w, blog); err != nil {
61+
// if err := jsonapi.MarshalPayload(w, blog); err != nil {
6262
// http.Error(w, err.Error(), 500)
6363
// }
6464
// }

request_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -931,7 +931,7 @@ func samplePayloadWithSideloaded() io.Reader {
931931
testModel := testModel()
932932

933933
out := bytes.NewBuffer(nil)
934-
MarshalOnePayload(out, testModel)
934+
MarshalPayload(out, testModel)
935935

936936
return out
937937
}

0 commit comments

Comments
 (0)