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