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 MarshalFields(query url.Values) MarshalOption
- func MarshalInclude(v ...any) MarshalOption
- func MarshalJSONAPI(meta any) MarshalOption
- func MarshalLinks(l *Link) MarshalOption
- func MarshalMeta(meta any) MarshalOption
- func MarshalSetNameValidation(mode MemberNameValidationMode) MarshalOption
- type Marshaler
- type MemberNameValidationError
- type MemberNameValidationMode
- 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\"") // ErrErrorUnmarshalingNotImplemented indicates that an attempt was made to unmarshal an error document ErrErrorUnmarshalingNotImplemented = errors.New("error unmarshaling is not implemented") )
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/DataDog/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/DataDog/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/DataDog/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/DataDog/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/DataDog/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/DataDog/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.1/#error-objects.
func (*Error) MarshalJSON ¶ added in v0.4.0
MarshalJSON implements the json.Marshaler interface.
func (*Error) UnmarshalJSON ¶ added in v0.7.2
UnmarshalJSON implements the json.Unmarshaler interface.
type ErrorLink ¶
ErrorLink represents a JSON:API error links object as defined by https://jsonapi.org/format/1.1/#error-objects.
type ErrorSource ¶
type ErrorSource struct { Pointer string `json:"pointer,omitempty"` Parameter string `json:"parameter,omitempty"` Header string `json:"header,omitempty"` }
ErrorSource represents a JSON:API Error.Source as defined by https://jsonapi.org/format/1.1/#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 ¶ added in v0.2.0
func MarshalClientMode() MarshalOption
MarshalClientMode enables client mode which skips validation only relevant for servers writing JSON:API responses.
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 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 MarshalSetNameValidation ¶ added in v0.8.0
func MarshalSetNameValidation(mode MemberNameValidationMode) MarshalOption
MarshalSetNameValidation enables a given level of document member name validation.
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 ¶ added in v0.5.0
type MemberNameValidationError struct {
MemberName string
}
MemberNameValidationError indicates that a document member name failed a validation step.
func (*MemberNameValidationError) Error ¶ added in v0.5.0
func (e *MemberNameValidationError) Error() string
Error implements the error interface.
type MemberNameValidationMode ¶ added in v0.8.0
type MemberNameValidationMode int
MemberNameValidationMode controls how document member names are checked for correctness.
const ( // DefaultValidation verifies that member names are valid according to the spec in // https://jsonapi.org/format/#document-member-names. // // Note that this validation mode allows for non-URL-safe member names. DefaultValidation MemberNameValidationMode = iota // DisableValidation turns off member name validation for convenience or performance-saving // reasons. // // Note that this validation mode allows member names that do NOT conform to the JSON:API spec. DisableValidation // StrictValidation verifies that member names are valid according to the spec in // https://jsonapi.org/format/#document-member-names, and follow recommendations from // https://jsonapi.org/recommendations/#naming. // // Note that these names are always URL-safe. StrictValidation )
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 UnmarshalLinks ¶ added in v0.10.0
func UnmarshalLinks(link *Link) UnmarshalOption
UnmarshalLinks copies the Document.Links into the given link.
func UnmarshalMeta ¶
func UnmarshalMeta(meta any) UnmarshalOption
UnmarshalMeta decodes Document.Meta into the given interface when unmarshaling.
Example ¶
package main import ( "fmt" "github.com/DataDog/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 UnmarshalSetNameValidation ¶ added in v0.8.0
func UnmarshalSetNameValidation(mode MemberNameValidationMode) UnmarshalOption
UnmarshalSetNameValidation enables a given level of document member name validation.
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.