Documentation
¶
Overview ¶
Package jsonapi implements encoding and decoding of JSON:API as defined in https://jsonapi.org/format/.
Index ¶
- Variables
- func Marshal(v any, opts ...MarshalOption) (b []byte, err error)
- func Status(s int) *int
- func Unmarshal(data []byte, v any, opts ...UnmarshalOption) (err error)
- type Error
- type ErrorLink
- type ErrorSource
- type Link
- type LinkObject
- type Linkable
- type LinkableRelation
- type MarshalIdentifier
- type MarshalOption
- func MarshalClientMode() MarshalOption
- func MarshalDisableNameValidation() MarshalOption
- func MarshalFields(query url.Values) MarshalOption
- func MarshalIgnoreAtMembers() MarshalOption
- func MarshalInclude(v ...any) MarshalOption
- func MarshalJSONAPI(meta any) MarshalOption
- func MarshalLinks(l *Link) MarshalOption
- func MarshalMeta(meta any) MarshalOption
- func MarshalStrictNameValidation() MarshalOption
- type Marshaler
- type MemberNameValidationError
- type PartialLinkageError
- type TagError
- type TypeError
- type UnmarshalIdentifier
- type UnmarshalOption
- type Unmarshaler
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( // ErrMarshalInvalidPrimaryField indicates that the id (primary) fields was invalid. ErrMarshalInvalidPrimaryField = errors.New("primary/id field must be a string or implement fmt.Stringer or in a struct which implements MarshalIdentifier") // ErrUnmarshalInvalidPrimaryField indicates that the id (primary) fields was invalid. ErrUnmarshalInvalidPrimaryField = errors.New("primary/id field must be a string or in a struct which implements UnmarshalIdentifer") // ErrUnmarshalDuplicatePrimaryField indicates that the id (primary) field is duplicated in a struct. ErrUnmarshalDuplicatePrimaryField = errors.New("there must be only one `jsonapi:\"primary\"` field to Unmarshal") // ErrMissingPrimaryField indicates that the id (primary) field is not identified. ErrMissingPrimaryField = errors.New("primary/id field must labeled with `jsonapi:\"primary,{type}\"`") // ErrEmptyPrimaryField indicates that the id (primary) field is identified but empty. ErrEmptyPrimaryField = errors.New("the `jsonapi:\"primary\"` field value must not be empty") // ErrMissingLinkFields indicates that a LinkObject is not valid. ErrMissingLinkFields = errors.New("at least one of Links.Self or Links.Related must be set to a nonempty string or *LinkObject") // ErrEmptyDataObject indicates that a primary or relationship data member is incorrectly represented by an empty JSON object {} ErrEmptyDataObject = errors.New("resource \"data\" members may not be represented by an empty object {}") // ErrDocumentMissingRequiredMembers indicates that a document does not have at least one required top-level member ErrDocumentMissingRequiredMembers = errors.New("document is missing required top-level members; must have one of: \"data\", \"meta\", \"errors\"") // ErrRelationshipMissingRequiredMembers indicates that a relationship does not have at least one required member ErrRelationshipMissingRequiredMembers = errors.New("relationship is missing required top-level members; must have one of: \"data\", \"meta\", \"links\"") )
Functions ¶
func Marshal ¶
func Marshal(v any, opts ...MarshalOption) (b []byte, err error)
Marshal returns the json:api encoding of v. If v is type *Error or []*Error only the errors will be marshaled.
Example ¶
package main import ( "fmt" "github.com/DQSevilla/jsonapi" ) func main() { type Article struct { ID string `jsonapi:"primary,articles"` Title string `jsonapi:"attribute" json:"title"` } a := Article{ID: "1", Title: "Hello World"} b, err := jsonapi.Marshal(&a) if err != nil { panic(err) } fmt.Printf("%s", string(b)) }
Output: {"data":{"id":"1","type":"articles","attributes":{"title":"Hello World"}}}
Example (Meta) ¶
package main import ( "fmt" "github.com/DQSevilla/jsonapi" ) func main() { type ArticleMeta struct { Views int `json:"views"` } type Article struct { ID string `jsonapi:"primary,articles"` Title string `jsonapi:"attribute" json:"title"` Meta *ArticleMeta `jsonapi:"meta"` } a := Article{ID: "1", Title: "Hello World", Meta: &ArticleMeta{Views: 10}} m := map[string]any{"foo": "bar"} b, err := jsonapi.Marshal(&a, jsonapi.MarshalMeta(m)) if err != nil { panic(err) } fmt.Printf("%s", string(b)) }
Output: {"data":{"id":"1","type":"articles","attributes":{"title":"Hello World"},"meta":{"views":10}},"meta":{"foo":"bar"}}
Example (Relationships) ¶
package main import ( "fmt" "github.com/DQSevilla/jsonapi" ) type Author struct { ID string `jsonapi:"primary,author"` Name string `jsonapi:"attribute" json:"name"` } type Comment struct { ID string `jsonapi:"primary,comments"` Body string `jsonapi:"attribute" json:"comment"` Author *Author `jsonapi:"relationship"` } func (c *Comment) LinkRelation(relation string) *jsonapi.Link { return &jsonapi.Link{ Self: fmt.Sprintf("http://example.com/comments/%s/relationships/%s", c.ID, relation), Related: fmt.Sprintf("http://example.com/comments/%s/%s", c.ID, relation), } } type Article struct { ID string `jsonapi:"primary,articles"` Title string `jsonapi:"attribute" json:"title"` Author *Author `jsonapi:"relationship" json:"author,omitempty"` Comments []*Comment `jsonapi:"relationship" json:"comments,omitempty"` } func (a *Article) LinkRelation(relation string) *jsonapi.Link { return &jsonapi.Link{ Self: fmt.Sprintf("http://example.com/articles/%s/relationships/%s", a.ID, relation), Related: fmt.Sprintf("http://example.com/articles/%s/%s", a.ID, relation), } } func main() { authorA := &Author{ID: "AA", Name: "Cool Author"} authorB := &Author{ID: "AB", Name: "Cool Commenter"} authorC := &Author{ID: "AC", Name: "Neat Commenter"} commentA := &Comment{ID: "CA", Body: "Very cool", Author: authorB} commentB := &Comment{ID: "CB", Body: "Super neat", Author: authorC} article := Article{ ID: "1", Title: "Hello World", Author: authorA, Comments: []*Comment{commentA, commentB}, } b, err := jsonapi.Marshal(&article) if err != nil { panic(err) } fmt.Printf("%s", string(b)) }
Output: {"data":{"id":"1","type":"articles","attributes":{"title":"Hello World"},"relationships":{"author":{"data":{"id":"AA","type":"author"},"links":{"self":"http://example.com/articles/1/relationships/author","related":"http://example.com/articles/1/author"}},"comments":{"data":[{"id":"CA","type":"comments"},{"id":"CB","type":"comments"}],"links":{"self":"http://example.com/articles/1/relationships/comments","related":"http://example.com/articles/1/comments"}}}}}
Example (Slice) ¶
package main import ( "fmt" "github.com/DQSevilla/jsonapi" ) func main() { type Article struct { ID string `jsonapi:"primary,articles"` Title string `jsonapi:"attribute" json:"title"` } a := []*Article{ {ID: "1", Title: "Hello World"}, {ID: "2", Title: "Hello Again"}, } b, err := jsonapi.Marshal(&a) if err != nil { panic(err) } fmt.Printf("%s", string(b)) }
Output: {"data":[{"id":"1","type":"articles","attributes":{"title":"Hello World"}},{"id":"2","type":"articles","attributes":{"title":"Hello Again"}}]}
func Unmarshal ¶
func Unmarshal(data []byte, v any, opts ...UnmarshalOption) (err error)
Unmarshal parses the json:api encoded data and stores the result in the value pointed to by v. If v is nil or not a pointer, Unmarshal returns an error.
Example ¶
package main import ( "fmt" "github.com/DQSevilla/jsonapi" ) func main() { body := `{"data":{"id":"1","type":"articles","attributes":{"title":"Hello World"}}}` type Article struct { ID string `jsonapi:"primary,articles"` Title string `jsonapi:"attribute" json:"title"` } var a Article err := jsonapi.Unmarshal([]byte(body), &a) if err != nil { panic(err) } fmt.Printf("%+v", &a) }
Output: &{ID:1 Title:Hello World}
Example (Slice) ¶
package main import ( "fmt" "github.com/DQSevilla/jsonapi" ) func main() { body := `{"data":[{"id":"1","type":"articles","attributes":{"title":"Hello World"}},{"id":"2","type":"articles","attributes":{"title":"Hello Again"}}]}` type Article struct { ID string `jsonapi:"primary,articles"` Title string `jsonapi:"attribute" json:"title"` } var a []*Article err := jsonapi.Unmarshal([]byte(body), &a) if err != nil { panic(err) } fmt.Printf("%+v %+v", a[0], a[1]) }
Output: &{ID:1 Title:Hello World} &{ID:2 Title:Hello Again}
Types ¶
type Error ¶
type Error struct { ID string `json:"id,omitempty"` Links *ErrorLink `json:"links,omitempty"` Status *int `json:"status,omitempty"` Code string `json:"code,omitempty"` Title string `json:"title,omitempty"` Detail string `json:"detail,omitempty"` Source *ErrorSource `json:"source,omitempty"` Meta any `json:"meta,omitempty"` }
Error represents a JSON:API error object as defined by https://jsonapi.org/format/1.0/#error-objects.
func (*Error) MarshalJSON ¶
MarshalJSON implements the json.Marshaler interface.
func (*Error) UnmarshalJSON ¶
UnmarshalJSON implements the json.Unmarshaler interface.
type ErrorLink ¶
type ErrorLink struct {
About any `json:"about,omitempty"`
}
ErrorLink represents a JSON:API error links object as defined by https://jsonapi.org/format/1.0/#error-objects.
type ErrorSource ¶
type ErrorSource struct { Pointer string `json:"pointer,omitempty"` Parameter string `json:"parameter,omitempty"` }
ErrorSource represents a JSON:API Error.Source as defined by https://jsonapi.org/format/1.0/#error-objects.
type Link ¶
type Link struct { Self any `json:"self,omitempty"` Related any `json:"related,omitempty"` First string `json:"first,omitempty"` Last string `json:"last,omitempty"` Next string `json:"next,omitempty"` Previous string `json:"previous,omitempty"` }
Link is the top-level links object as defined by https://jsonapi.org/format/1.0/#document-top-level. First|Last|Next|Previous are provided to support pagination as defined by https://jsonapi.org/format/1.0/#fetching-pagination.
type LinkObject ¶
LinkObject is a links object as defined by https://jsonapi.org/format/1.0/#document-links
type Linkable ¶
type Linkable interface {
Link() *Link
}
Linkable can be implemented to marshal resource object links as defined by https://jsonapi.org/format/1.0/#document-resource-object-links.
type LinkableRelation ¶
LinkableRelation can be implemented to marshal resource object related resource links as defined by https://jsonapi.org/format/1.0/#document-resource-object-related-resource-links.
type MarshalIdentifier ¶
type MarshalIdentifier interface {
MarshalID() string
}
MarshalIdentifier can be optionally implemented to control marshaling of the primary field to a string.
The order of operations for marshaling the primary field is:
- Use MarshalIdentifier if it is implemented
- Use the value directly if it is a string
- Use fmt.Stringer if it is implemented
- Fail
type MarshalOption ¶
type MarshalOption func(m *Marshaler)
MarshalOption allows for configuration of Marshaling.
func MarshalClientMode ¶
func MarshalClientMode() MarshalOption
MarshalClientMode enables client mode which skips validation only relevant for servers writing JSON:API responses.
func MarshalDisableNameValidation ¶ added in v0.7.3
func MarshalDisableNameValidation() MarshalOption
MarshalDisableNameValidation turns off member name validation, which may be useful for compatibility or performance reasons.
Note that this option allows you to use member names which do not conform to the JSON:API spec. See https://jsonapi.org/format/#document-member-names.
func MarshalFields ¶
func MarshalFields(query url.Values) MarshalOption
MarshalFields supports sparse fieldsets as defined by https://jsonapi.org/format/1.0/#fetching-sparse-fieldsets. The input is a url.Values and if given only the fields included in `fields[type]=a,b` are included in the response.
func MarshalIgnoreAtMembers ¶ added in v0.7.5
func MarshalIgnoreAtMembers() MarshalOption
func MarshalInclude ¶
func MarshalInclude(v ...any) MarshalOption
MarshalInclude includes the json:api encoding of v within Document.Included creating a compound document as defined by https://jsonapi.org/format/#document-compound-documents.
func MarshalJSONAPI ¶
func MarshalJSONAPI(meta any) MarshalOption
MarshalJSONAPI includes the given meta (must be a map or struct) as Document.JSONAPI.Meta when marshaling. This also enables writing Document.JSONAPI.Version.
func MarshalLinks ¶
func MarshalLinks(l *Link) MarshalOption
MarshalLinks includes the given links as Document.Links when marshaling.
func MarshalMeta ¶
func MarshalMeta(meta any) MarshalOption
MarshalMeta includes the given meta (must be a map or struct) as Document.Meta when marshaling.
func MarshalStrictNameValidation ¶ added in v0.7.3
func MarshalStrictNameValidation() MarshalOption
MarshalStrictNameValidation enables member name validation that is more strict than default.
In addition to the basic naming rules from https://jsonapi.org/format/#document-member-names, this option follows guidelines from https://jsonapi.org/recommendations/#naming.
type Marshaler ¶
type Marshaler struct {
// contains filtered or unexported fields
}
Marshaler is configured internally via MarshalOption's passed to Marshal. It's used to configure the Marshaling by including optional fields like Meta or JSONAPI.
type MemberNameValidationError ¶
type MemberNameValidationError struct {
MemberName string
}
MemberNameValidationError indicates that a document member name failed a validation step.
func (*MemberNameValidationError) Error ¶
func (e *MemberNameValidationError) Error() string
Error implements the error interface.
type PartialLinkageError ¶
type PartialLinkageError struct {
// contains filtered or unexported fields
}
PartialLinkageError indicates that an incomplete relationship chain was encountered.
func (*PartialLinkageError) Error ¶
func (e *PartialLinkageError) Error() string
Error implements the error interface.
type UnmarshalIdentifier ¶
UnmarshalIdentifier can be optionally implemented to control unmarshaling of the primary field from a string.
The order of operations for unmarshaling the primary field is:
- Use UnmarshalIdentifier if it is implemented
- Use the value directly if it is a string
- Fail
type UnmarshalOption ¶
type UnmarshalOption func(m *Unmarshaler)
UnmarshalOption allows for configuration of Unmarshaling.
func UnmarshalDisableNameValidation ¶ added in v0.7.3
func UnmarshalDisableNameValidation() UnmarshalOption
UnmarshalDisableNameValidation turns off member name validation, which may be useful for compatibility or performance reasons.
Note that this option allows you to use member names which do not conform to the JSON:API spec. See https://jsonapi.org/format/#document-member-names.
func UnmarshalMeta ¶
func UnmarshalMeta(meta any) UnmarshalOption
UnmarshalMeta decodes Document.Meta into the given interface when unmarshaling.
Example ¶
package main import ( "fmt" "github.com/DQSevilla/jsonapi" ) func main() { body := `{"data":{"id":"1","type":"articles","attributes":{"title":"Hello World"},"meta":{"views":10}},"meta":{"foo":"bar"}}` type ArticleMeta struct { Views int `json:"views"` } type Article struct { ID string `jsonapi:"primary,articles"` Title string `jsonapi:"attribute" json:"title"` Meta *ArticleMeta `jsonapi:"meta"` } var ( a Article m map[string]any ) err := jsonapi.Unmarshal([]byte(body), &a, jsonapi.UnmarshalMeta(&m)) if err != nil { panic(err) } fmt.Printf("%s %s %+v %+v", a.ID, a.Title, a.Meta, m) }
Output: 1 Hello World &{Views:10} map[foo:bar]
func UnmarshalStrictNameValidation ¶ added in v0.7.3
func UnmarshalStrictNameValidation() UnmarshalOption
UnmarshalStrictNameValidation enables member name validation that is more strict than default.
In addition to the basic naming rules from https://jsonapi.org/format/#document-member-names, this option follows guidelines from https://jsonapi.org/recommendations/#naming.
type Unmarshaler ¶
type Unmarshaler struct {
// contains filtered or unexported fields
}
Unmarshaler is configured internally via UnmarshalOption's passed to Unmarshal. It's used to configure the Unmarshaling by decoding optional fields like Meta.