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 Timestamp struct {
29	ID   int        `jsonapi:"primary,timestamps"`
30	Time time.Time  `jsonapi:"attr,timestamp,iso8601"`
31	Next *time.Time `jsonapi:"attr,next,iso8601"`
32}
33
34type Car struct {
35	ID    *string `jsonapi:"primary,cars"`
36	Make  *string `jsonapi:"attr,make,omitempty"`
37	Model *string `jsonapi:"attr,model,omitempty"`
38	Year  *uint   `jsonapi:"attr,year,omitempty"`
39}
40
41type Post struct {
42	Blog
43	ID            uint64     `jsonapi:"primary,posts"`
44	BlogID        int        `jsonapi:"attr,blog_id"`
45	ClientID      string     `jsonapi:"client-id"`
46	Title         string     `jsonapi:"attr,title"`
47	Body          string     `jsonapi:"attr,body"`
48	Comments      []*Comment `jsonapi:"relation,comments"`
49	LatestComment *Comment   `jsonapi:"relation,latest_comment"`
50}
51
52type Comment struct {
53	ID       int    `jsonapi:"primary,comments"`
54	ClientID string `jsonapi:"client-id"`
55	PostID   int    `jsonapi:"attr,post_id"`
56	Body     string `jsonapi:"attr,body"`
57}
58
59type Book struct {
60	ID          uint64  `jsonapi:"primary,books"`
61	Author      string  `jsonapi:"attr,author"`
62	ISBN        string  `jsonapi:"attr,isbn"`
63	Title       string  `jsonapi:"attr,title,omitempty"`
64	Description *string `jsonapi:"attr,description"`
65	Pages       *uint   `jsonapi:"attr,pages,omitempty"`
66	PublishedAt time.Time
67	Tags        []string `jsonapi:"attr,tags"`
68}
69
70type Blog struct {
71	ID            int       `jsonapi:"primary,blogs"`
72	ClientID      string    `jsonapi:"client-id"`
73	Title         string    `jsonapi:"attr,title"`
74	Posts         []*Post   `jsonapi:"relation,posts"`
75	CurrentPost   *Post     `jsonapi:"relation,current_post"`
76	CurrentPostID int       `jsonapi:"attr,current_post_id"`
77	CreatedAt     time.Time `jsonapi:"attr,created_at"`
78	ViewCount     int       `jsonapi:"attr,view_count"`
79}
80
81func (b *Blog) JSONAPILinks() *Links {
82	return &Links{
83		"self": fmt.Sprintf("https://example.com/api/blogs/%d", b.ID),
84		"comments": Link{
85			Href: fmt.Sprintf("https://example.com/api/blogs/%d/comments", b.ID),
86			Meta: Meta{
87				"counts": map[string]uint{
88					"likes":    4,
89					"comments": 20,
90				},
91			},
92		},
93	}
94}
95
96func (b *Blog) JSONAPIRelationshipLinks(relation string) *Links {
97	if relation == "posts" {
98		return &Links{
99			"related": Link{
100				Href: fmt.Sprintf("https://example.com/api/blogs/%d/posts", b.ID),
101				Meta: Meta{
102					"count": len(b.Posts),
103				},
104			},
105		}
106	}
107	if relation == "current_post" {
108		return &Links{
109			"self": fmt.Sprintf("https://example.com/api/posts/%s", "3"),
110			"related": Link{
111				Href: fmt.Sprintf("https://example.com/api/blogs/%d/current_post", b.ID),
112			},
113		}
114	}
115	return nil
116}
117
118func (b *Blog) JSONAPIMeta() *Meta {
119	return &Meta{
120		"detail": "extra details regarding the blog",
121	}
122}
123
124func (b *Blog) JSONAPIRelationshipMeta(relation string) *Meta {
125	if relation == "posts" {
126		return &Meta{
127			"this": map[string]interface{}{
128				"can": map[string]interface{}{
129					"go": []interface{}{
130						"as",
131						"deep",
132						map[string]interface{}{
133							"as": "required",
134						},
135					},
136				},
137			},
138		}
139	}
140	if relation == "current_post" {
141		return &Meta{
142			"detail": "extra current_post detail",
143		}
144	}
145	return nil
146}
147
148type BadComment struct {
149	ID   uint64 `jsonapi:"primary,bad-comment"`
150	Body string `jsonapi:"attr,body"`
151}
152
153func (bc *BadComment) JSONAPILinks() *Links {
154	return &Links{
155		"self": []string{"invalid", "should error"},
156	}
157}
158
159type Company struct {
160	ID        string    `jsonapi:"primary,companies"`
161	Name      string    `jsonapi:"attr,name"`
162	Boss      Employee  `jsonapi:"attr,boss"`
163	Teams     []Team    `jsonapi:"attr,teams"`
164	FoundedAt time.Time `jsonapi:"attr,founded-at,iso8601"`
165}
166
167type Team struct {
168	Name    string     `json:"name"`
169	Leader  *Employee  `json:"leader"`
170	Members []Employee `json:"members"`
171}
172
173type Employee struct {
174	Firstname string     `json:"firstname"`
175	Surname   string     `json:"surname"`
176	Age       int        `json:"age"`
177	HiredAt   *time.Time `json:"hired-at,iso8601"`
178}
179
180type CustomIntType int
181type CustomFloatType float64
182type CustomStringType string
183
184type CustomAttributeTypes struct {
185	ID string `jsonapi:"primary,customtypes"`
186
187	Int        CustomIntType  `jsonapi:"attr,int"`
188	IntPtr     *CustomIntType `jsonapi:"attr,intptr"`
189	IntPtrNull *CustomIntType `jsonapi:"attr,intptrnull"`
190
191	Float  CustomFloatType  `jsonapi:"attr,float"`
192	String CustomStringType `jsonapi:"attr,string"`
193}
194