Skip to content

Commit 0ee11bd

Browse files
committed
Merge pull request #202 from manyminds/internal-data-structs
Major Refactoring: Fully typed structs that represent a jsonapi document
2 parents 8fbbd12 + 4814f9b commit 0ee11bd

31 files changed

+2214
-2297
lines changed

README.md

Lines changed: 76 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ In order to get updates in the future there are two ways to possible ways for yo
2525

2626
## TOC
2727
- [Installation](#installation)
28+
- [Basic funtionality](#basic-functionality)
2829
- [Examples](#examples)
2930
- [Interfaces to implement](#interfaces-to-implement)
3031
- [Responder](#responder)
@@ -33,7 +34,6 @@ In order to get updates in the future there are two ways to possible ways for yo
3334
- [UnmarshalIdentifier](#unmarshalidentifier)
3435
- [Marshalling with References to other structs](#marshalling-with-references-to-other-structs)
3536
- [Unmarshalling with references to other structs](#unmarshalling-with-references-to-other-structs)
36-
- [Ignoring fields](#ignoring-fields)
3737
- [Manual marshaling / unmarshaling](#manual-marshaling--unmarshaling)
3838
- [SQL Null-Types](#sql-null-types)
3939
- [Using api2go with the gin framework](#api2go-with-gin)
@@ -58,6 +58,54 @@ If you only need marshalling and/or unmarshalling:
5858
go get gopkg.in/manyminds/api2go.v0/jsonapi
5959
```
6060

61+
## Basic functionality
62+
Api2go will Marshal/Unmarshal exactly like the internal `json` package from Go
63+
with one addition: It will decorate the Marshaled json with jsonapi meta
64+
objects. Jsonapi wraps the payload inside an `attributes` object. The rest is
65+
just Meta-Data which will be generated by Api2go.
66+
67+
So let's take this basic example:
68+
69+
```go
70+
type Article struct {
71+
ID string
72+
Title string `json:"title"`
73+
}
74+
```
75+
76+
Would `json.Marshal` into this Json:
77+
78+
```json
79+
{
80+
"ID": "Some-ID",
81+
"title": "the title"
82+
}
83+
```
84+
85+
For api2go, you have to ignore tag the `ID` field and then the result could be
86+
something like this:
87+
88+
```json
89+
{
90+
"type": "articles",
91+
"id": "1",
92+
"attributes": {
93+
"title": "Rails is Omakase"
94+
},
95+
"relationships": {
96+
"author": {
97+
"links": {
98+
"self": "/articles/1/relationships/author",
99+
"related": "/articles/1/author"
100+
},
101+
"data": { "type": "people", "id": "9" }
102+
}
103+
}
104+
}
105+
```
106+
107+
All the additional information is retrieved by implementing some interface
108+
methods.
61109

62110
## Examples
63111

@@ -70,16 +118,16 @@ comments that belong with a has-many relation to the post.
70118

71119
```go
72120
type Post struct {
73-
ID int `jsonapi:"-"` // Ignore ID field because the ID is fetched via the
74-
// GetID() method and must not be inside the attributes object.
75-
Title string
76-
Comments []Comment `jsonapi:"-"` // this will be ignored by the api2go marshaller
77-
CommentsIDs []int `jsonapi:"-"` // it's only useful for our internal relationship handling
121+
ID int `json:"-"` // Ignore ID field because the ID is fetched via the
122+
// GetID() method and must not be inside the attributes object.
123+
Title string `json:"title"`
124+
Comments []Comment `json:"-"` // this will be ignored by the api2go marshaller
125+
CommentsIDs []int `json:"-"` // it's only useful for our internal relationship handling
78126
}
79127

80128
type Comment struct {
81-
ID int
82-
Text string `jsonapi:"name=content"`
129+
ID int `json:"-"`
130+
Text string `json:"text"`
83131
}
84132
```
85133

@@ -91,8 +139,7 @@ In the Post example struct, the `ID` field is ignored because api2go will use th
91139
Every field inside a struct will be marshaled into the `attributes` object in
92140
the json. In our example, we just want to have the `Title` field there.
93141

94-
In order to use different internal names for elements, you can specify a jsonapi tag. The api will marshal results now with the name in the tag.
95-
Create/Update/Delete works accordingly, but will fallback to the internal value as well if possible.
142+
Don't forget to name all your fields with the `json:"yourName"` tag.
96143

97144
### Responder
98145
```go
@@ -210,10 +257,6 @@ type UnmarshalToManyRelations interface {
210257

211258
**If you need to know more about how to use the interfaces, look at our tests or at the example project.**
212259

213-
## Ignoring fields
214-
api2go ignores all fields that are marked with the `jsonapi:"-"` ignore tag. This is useful if your struct has some more
215-
fields which are only used internally to manage relations or data that needs to stay private, like a password field.
216-
217260
## Manual marshaling / unmarshaling
218261
Please keep in mind that this only works if you implemented the previously mentioned interfaces. Manual marshalling and
219262
unmarshalling makes sense, if you do not want to use our API that automatically generates all the necessary routes for you. You
@@ -224,7 +267,7 @@ comment1 = Comment{ID: 1, Text: "First!"}
224267
comment2 = Comment{ID: 2, Text: "Second!"}
225268
post = Post{ID: 1, Title: "Foobar", Comments: []Comment{comment1, comment2}}
226269

227-
json, err := jsonapi.MarshalToJSON(post)
270+
json, err := jsonapi.Marshal(post)
228271
```
229272

230273
will yield
@@ -235,6 +278,9 @@ will yield
235278
{
236279
"id": "1",
237280
"type": "posts",
281+
"attributes": {
282+
"title": "Foobar"
283+
},
238284
"relationships": {
239285
"comments": {
240286
"data": [
@@ -246,43 +292,48 @@ will yield
246292
"id": "2",
247293
"type": "comments"
248294
}
249-
],
295+
]
250296
}
251-
},
252-
"title": "Foobar"
297+
}
253298
}
254299
],
255300
"included": [
256301
{
257302
"id": "1",
258303
"type": "comments",
259-
"text": "First!"
304+
"attributes": {
305+
"text": "First!"
306+
}
260307
},
261308
{
262309
"id": "2",
263310
"type": "comments",
264-
"text": "Second!"
311+
"attributes": {
312+
"text": "Second!"
313+
}
265314
}
266315
]
267316
}
268317
```
269318

270-
You can also use `jsonapi.MarshalToJSONWithURLs` to automatically generate URLs for the rest endpoints that have a
319+
You can also use `jsonapi.MarshalWithURLs` to automatically generate URLs for the rest endpoints that have a
271320
version and BaseURL prefix. This will generate the same routes that our API uses. This adds `self` and `related` fields
272321
for relations inside the `relationships` object.
273322

274-
Recover the structure from above using
323+
Recover the structure from above using. Keep in mind that Unmarshaling with
324+
included structs does not work yet. So Api2go cannot be used as a client yet.
275325

276326
```go
277327
var posts []Post
278-
err := jsonapi.UnmarshalFromJSON(json, &posts)
328+
err := jsonapi.Unmarshal(json, &posts)
279329
// posts[0] == Post{ID: 1, Title: "Foobar", CommentsIDs: []int{1, 2}}
280330
```
281331

282332
If on the other hand you want to change the response encoding while still taking advantage of the autogenerated logic
283333
you need to provide a `ContentMarshaler` for each `Content-Type` you would like to support.
284334

285-
The `ContentMarshaler` interface declares two functions
335+
The `ContentMarshaler` interface declares two functions **deprecated, we have
336+
to figure out what to do with this yet**
286337

287338
```go
288339
type ContentMarshaler interface {
@@ -496,7 +547,7 @@ all query parameters as `map[string][]string` unfiltered. So you can use it for:
496547
```go
497548
type fixtureSource struct {}
498549

499-
func (s *fixtureSource) FindAll(req api2go.Request) (interface{}, error) {
550+
func (s *fixtureSource) FindAll(req api2go.Request) (Responder, error) {
500551
for key, values range req.QueryParams {
501552
...
502553
}

0 commit comments

Comments
 (0)