1package jsonapi
2
3import "fmt"
4
5// Payloader is used to encapsulate the One and Many payload types
6type Payloader interface {
7	clearIncluded()
8}
9
10// OnePayload is used to represent a generic JSON API payload where a single
11// resource (Node) was included as an {} in the "data" key
12type OnePayload struct {
13	Data     *Node   `json:"data"`
14	Included []*Node `json:"included,omitempty"`
15	Links    *Links  `json:"links,omitempty"`
16	Meta     *Meta   `json:"meta,omitempty"`
17}
18
19func (p *OnePayload) clearIncluded() {
20	p.Included = []*Node{}
21}
22
23// ManyPayload is used to represent a generic JSON API payload where many
24// resources (Nodes) were included in an [] in the "data" key
25type ManyPayload struct {
26	Data     []*Node `json:"data"`
27	Included []*Node `json:"included,omitempty"`
28	Links    *Links  `json:"links,omitempty"`
29	Meta     *Meta   `json:"meta,omitempty"`
30}
31
32func (p *ManyPayload) clearIncluded() {
33	p.Included = []*Node{}
34}
35
36// Node is used to represent a generic JSON API Resource
37type Node struct {
38	Type          string                 `json:"type"`
39	ID            string                 `json:"id,omitempty"`
40	ClientID      string                 `json:"client-id,omitempty"`
41	Attributes    map[string]interface{} `json:"attributes,omitempty"`
42	Relationships map[string]interface{} `json:"relationships,omitempty"`
43	Links         *Links                 `json:"links,omitempty"`
44	Meta          *Meta                  `json:"meta,omitempty"`
45}
46
47// RelationshipOneNode is used to represent a generic has one JSON API relation
48type RelationshipOneNode struct {
49	Data  *Node  `json:"data"`
50	Links *Links `json:"links,omitempty"`
51	Meta  *Meta  `json:"meta,omitempty"`
52}
53
54// RelationshipManyNode is used to represent a generic has many JSON API
55// relation
56type RelationshipManyNode struct {
57	Data  []*Node `json:"data"`
58	Links *Links  `json:"links,omitempty"`
59	Meta  *Meta   `json:"meta,omitempty"`
60}
61
62// Links is used to represent a `links` object.
63// http://jsonapi.org/format/#document-links
64type Links map[string]interface{}
65
66func (l *Links) validate() (err error) {
67	// Each member of a links object is a “link”. A link MUST be represented as
68	// either:
69	//  - a string containing the link’s URL.
70	//  - an object (“link object”) which can contain the following members:
71	//    - href: a string containing the link’s URL.
72	//    - meta: a meta object containing non-standard meta-information about the
73	//            link.
74	for k, v := range *l {
75		_, isString := v.(string)
76		_, isLink := v.(Link)
77
78		if !(isString || isLink) {
79			return fmt.Errorf(
80				"The %s member of the links object was not a string or link object",
81				k,
82			)
83		}
84	}
85	return
86}
87
88// Link is used to represent a member of the `links` object.
89type Link struct {
90	Href string `json:"href"`
91	Meta Meta   `json:"meta,omitempty"`
92}
93
94// Linkable is used to include document links in response data
95// e.g. {"self": "http://example.com/posts/1"}
96type Linkable interface {
97	JSONAPILinks() *Links
98}
99
100// RelationshipLinkable is used to include relationship links  in response data
101// e.g. {"related": "http://example.com/posts/1/comments"}
102type RelationshipLinkable interface {
103	// JSONAPIRelationshipLinks will be invoked for each relationship with the corresponding relation name (e.g. `comments`)
104	JSONAPIRelationshipLinks(relation string) *Links
105}
106
107// Meta is used to represent a `meta` object.
108// http://jsonapi.org/format/#document-meta
109type Meta map[string]interface{}
110
111// Metable is used to include document meta in response data
112// e.g. {"foo": "bar"}
113type Metable interface {
114	JSONAPIMeta() *Meta
115}
116
117// RelationshipMetable is used to include relationship meta in response data
118type RelationshipMetable interface {
119	// JSONRelationshipMeta will be invoked for each relationship with the corresponding relation name (e.g. `comments`)
120	JSONAPIRelationshipMeta(relation string) *Meta
121}
122