1package jsonapi
2
3import (
4	"fmt"
5	"time"
6)
7
8type BadModel struct {
9	ID int `jsonapi:"primary"`
10}
11
12type ModelBadTypes struct {
13	ID           string     `jsonapi:"primary,badtypes"`
14	StringField  string     `jsonapi:"attr,string_field"`
15	FloatField   float64    `jsonapi:"attr,float_field"`
16	TimeField    time.Time  `jsonapi:"attr,time_field"`
17	TimePtrField *time.Time `jsonapi:"attr,time_ptr_field"`
18}
19
20type WithPointer struct {
21	ID       *uint64  `jsonapi:"primary,with-pointers"`
22	Name     *string  `jsonapi:"attr,name"`
23	IsActive *bool    `jsonapi:"attr,is-active"`
24	IntVal   *int     `jsonapi:"attr,int-val"`
25	FloatVal *float32 `jsonapi:"attr,float-val"`
26}
27
28type TimestampModel struct {
29	ID       int        `jsonapi:"primary,timestamps"`
30	DefaultV time.Time  `jsonapi:"attr,defaultv"`
31	DefaultP *time.Time `jsonapi:"attr,defaultp"`
32	ISO8601V time.Time  `jsonapi:"attr,iso8601v,iso8601"`
33	ISO8601P *time.Time `jsonapi:"attr,iso8601p,iso8601"`
34	RFC3339V time.Time  `jsonapi:"attr,rfc3339v,rfc3339"`
35	RFC3339P *time.Time `jsonapi:"attr,rfc3339p,rfc3339"`
36}
37
38type Car struct {
39	ID    *string `jsonapi:"primary,cars"`
40	Make  *string `jsonapi:"attr,make,omitempty"`
41	Model *string `jsonapi:"attr,model,omitempty"`
42	Year  *uint   `jsonapi:"attr,year,omitempty"`
43}
44
45type Post struct {
46	Blog
47	ID            uint64     `jsonapi:"primary,posts"`
48	BlogID        int        `jsonapi:"attr,blog_id"`
49	ClientID      string     `jsonapi:"client-id"`
50	Title         string     `jsonapi:"attr,title"`
51	Body          string     `jsonapi:"attr,body"`
52	Comments      []*Comment `jsonapi:"relation,comments"`
53	LatestComment *Comment   `jsonapi:"relation,latest_comment"`
54
55	Links Links `jsonapi:"links,omitempty"`
56}
57
58type Comment struct {
59	ID       int    `jsonapi:"primary,comments"`
60	ClientID string `jsonapi:"client-id"`
61	PostID   int    `jsonapi:"attr,post_id"`
62	Body     string `jsonapi:"attr,body"`
63
64	Links Links `jsonapi:"links,omitempty"`
65}
66
67type Book struct {
68	ID          uint64  `jsonapi:"primary,books"`
69	Author      string  `jsonapi:"attr,author"`
70	ISBN        string  `jsonapi:"attr,isbn"`
71	Title       string  `jsonapi:"attr,title,omitempty"`
72	Description *string `jsonapi:"attr,description"`
73	Pages       *uint   `jsonapi:"attr,pages,omitempty"`
74	PublishedAt time.Time
75	Tags        []string `jsonapi:"attr,tags"`
76}
77
78type Blog struct {
79	ID            int       `jsonapi:"primary,blogs"`
80	ClientID      string    `jsonapi:"client-id"`
81	Title         string    `jsonapi:"attr,title"`
82	Posts         []*Post   `jsonapi:"relation,posts"`
83	CurrentPost   *Post     `jsonapi:"relation,current_post"`
84	CurrentPostID int       `jsonapi:"attr,current_post_id"`
85	CreatedAt     time.Time `jsonapi:"attr,created_at"`
86	ViewCount     int       `jsonapi:"attr,view_count"`
87
88	Links Links `jsonapi:"links,omitempty"`
89}
90
91func (b *Blog) JSONAPILinks() *Links {
92	return &Links{
93		"self": fmt.Sprintf("https://example.com/api/blogs/%d", b.ID),
94		"comments": Link{
95			Href: fmt.Sprintf("https://example.com/api/blogs/%d/comments", b.ID),
96			Meta: Meta{
97				"counts": map[string]uint{
98					"likes":    4,
99					"comments": 20,
100				},
101			},
102		},
103	}
104}
105
106func (b *Blog) JSONAPIRelationshipLinks(relation string) *Links {
107	if relation == "posts" {
108		return &Links{
109			"related": Link{
110				Href: fmt.Sprintf("https://example.com/api/blogs/%d/posts", b.ID),
111				Meta: Meta{
112					"count": len(b.Posts),
113				},
114			},
115		}
116	}
117	if relation == "current_post" {
118		return &Links{
119			"self": fmt.Sprintf("https://example.com/api/posts/%s", "3"),
120			"related": Link{
121				Href: fmt.Sprintf("https://example.com/api/blogs/%d/current_post", b.ID),
122			},
123		}
124	}
125	return nil
126}
127
128func (b *Blog) JSONAPIMeta() *Meta {
129	return &Meta{
130		"detail": "extra details regarding the blog",
131	}
132}
133
134func (b *Blog) JSONAPIRelationshipMeta(relation string) *Meta {
135	if relation == "posts" {
136		return &Meta{
137			"this": map[string]interface{}{
138				"can": map[string]interface{}{
139					"go": []interface{}{
140						"as",
141						"deep",
142						map[string]interface{}{
143							"as": "required",
144						},
145					},
146				},
147			},
148		}
149	}
150	if relation == "current_post" {
151		return &Meta{
152			"detail": "extra current_post detail",
153		}
154	}
155	return nil
156}
157
158type BadComment struct {
159	ID   uint64 `jsonapi:"primary,bad-comment"`
160	Body string `jsonapi:"attr,body"`
161}
162
163func (bc *BadComment) JSONAPILinks() *Links {
164	return &Links{
165		"self": []string{"invalid", "should error"},
166	}
167}
168
169type Company struct {
170	ID        string    `jsonapi:"primary,companies"`
171	Name      string    `jsonapi:"attr,name"`
172	Boss      Employee  `jsonapi:"attr,boss"`
173	Teams     []Team    `jsonapi:"attr,teams"`
174	People    []*People `jsonapi:"attr,people"`
175	FoundedAt time.Time `jsonapi:"attr,founded-at,iso8601"`
176}
177
178type People struct {
179	Name string `jsonapi:"attr,name"`
180	Age  int    `jsonapi:"attr,age"`
181}
182
183type Team struct {
184	Name    string     `jsonapi:"attr,name"`
185	Leader  *Employee  `jsonapi:"attr,leader"`
186	Members []Employee `jsonapi:"attr,members"`
187}
188
189type Employee struct {
190	Firstname string     `jsonapi:"attr,firstname"`
191	Surname   string     `jsonapi:"attr,surname"`
192	Age       int        `jsonapi:"attr,age"`
193	HiredAt   *time.Time `jsonapi:"attr,hired-at,iso8601"`
194}
195
196type CustomIntType int
197type CustomFloatType float64
198type CustomStringType string
199
200type CustomAttributeTypes struct {
201	ID string `jsonapi:"primary,customtypes"`
202
203	Int        CustomIntType  `jsonapi:"attr,int"`
204	IntPtr     *CustomIntType `jsonapi:"attr,intptr"`
205	IntPtrNull *CustomIntType `jsonapi:"attr,intptrnull"`
206
207	Float  CustomFloatType  `jsonapi:"attr,float"`
208	String CustomStringType `jsonapi:"attr,string"`
209}
210