Documentation
¶
Overview ¶
Package resources transforms data into the shapes a JSON response takes: conditional fields, wrapping, pagination metadata and resource collections.
Sub-packages:
resources/json -- the JSON response building blocks resources/jsonapi -- JsonApiResource, JsonApiRequest
JsonResource is an interface that any type can implement, and Resource is the concrete one most applications embed. A set of helper functions -- When, Unless, WhenNotNull, MergeWhen and the rest -- build JSON responses with conditional fields: when a value is missing, it is omitted from the output rather than appearing as null.
Index ¶
- Constants
- Variables
- func Filter(data map[string]any) map[string]any
- func FlushState()
- func ForceWrapping(force bool)
- func MergeWhen(condition bool, value any) any
- func Transform(value any, callback func(any) any) any
- func Unless(condition bool, value any) any
- func When(condition bool, value any) any
- func WhenAggregated(relation, column, aggregate string, loaded bool, value any) any
- func WhenAppended(attribute string, appended bool, value any) any
- func WhenCounted(relation string, counted bool, value any) any
- func WhenExistsLoaded(relation string, loaded bool, value any) any
- func WhenHas(data map[string]any, key string, value any) any
- func WhenLoaded(relation string, loaded bool, value any) any
- func WhenNotNull(value any) any
- func WhenPivotLoaded(table string, loaded bool, value any) any
- func WhenPivotLoadedAs(accessor, table string, loaded bool, value any) any
- func WithoutWrapping()
- func Wrap(value string)
- func Wrapper() string
- type AnonymousResourceCollection
- type Arrayable
- type JsonResource
- type JsonResponseBuilder
- func (b *JsonResponseBuilder) Additional(data map[string]any) *JsonResponseBuilder
- func (b *JsonResponseBuilder) Build() ([]byte, error)
- func (b *JsonResponseBuilder) Status(code int) *JsonResponseBuilder
- func (b *JsonResponseBuilder) ToHTTPResponse() *http.Response
- func (b *JsonResponseBuilder) WithWrap(key string) *JsonResponseBuilder
- func (b *JsonResponseBuilder) WithoutWrapping() *JsonResponseBuilder
- type MergeValue
- type MissingValue
- type PaginatedResourceResponse
- type PotentiallyMissing
- type Resource
- func (r *Resource) Additional(data map[string]any) *Resource
- func (r *Resource) GetRouteKey() any
- func (r *Resource) GetRouteKeyName() string
- func (r *Resource) JsonSerialize() map[string]any
- func (r *Resource) Resolve() map[string]any
- func (r *Resource) ResolveChildRouteBinding(childType string, value any, field string) (any, error)
- func (r *Resource) ResolveResourceData() map[string]any
- func (r *Resource) ResolveRouteBinding(value any, field string) (any, error)
- func (r *Resource) Response() (*hhttp.JsonResponse, error)
- func (r *Resource) ToArray() map[string]any
- func (r *Resource) ToAttributes() map[string]any
- func (r *Resource) ToJson() ([]byte, error)
- func (r *Resource) ToPrettyJson() ([]byte, error)
- func (r *Resource) ToResponse() (*hhttp.JsonResponse, error)
- func (r *Resource) With() map[string]any
- func (r *Resource) WithResponse(response *hhttp.JsonResponse)
- type ResourceCollection
- func (c *ResourceCollection) Collects() string
- func (c *ResourceCollection) Count() int
- func (c *ResourceCollection) GetIterator() iter.Seq[JsonResource]
- func (c *ResourceCollection) PreserveQuery() *ResourceCollection
- func (c *ResourceCollection) QueryParameters() (map[string]string, bool)
- func (c *ResourceCollection) ToArray() map[string]any
- func (c *ResourceCollection) With() map[string]any
- func (c *ResourceCollection) WithQuery(query map[string]string) *ResourceCollection
- type UrlRoutable
Constants ¶
const DefaultWrap = "data"
DefaultWrap is the key the outermost resource map is nested under, by default.
Variables ¶
var ErrNotRouteBindable = errors.New("http/resources: resources may not be implicitly resolved from route bindings")
ErrNotRouteBindable is returned by ResolveRouteBinding and ResolveChildRouteBinding: a resource is a view of a model, not a thing the router can look up.
Functions ¶
func Filter ¶
Filter removes MissingValue entries from a map, and resolves MergeValue entries by merging their data into the parent.
func FlushState ¶
func FlushState()
FlushState puts the wrapper back to "data" and turns forced wrapping off.
func ForceWrapping ¶
func ForceWrapping(force bool)
ForceWrapping sets whether to wrap even when the resource data already carries the wrapper key.
Package-level state needs an exported function to reach it from outside the package, since an unexported field on a package variable is otherwise unreachable.
func MergeWhen ¶
MergeWhen creates a MergeValue if the condition is true, otherwise returns a MissingValue.
func When ¶
When returns value if condition is true, otherwise returns a MissingValue (which is filtered out during response serialization).
func WhenAggregated ¶
WhenAggregated returns value if the aggregate has been loaded.
func WhenAppended ¶
WhenAppended returns value if the attribute has been appended.
func WhenCounted ¶
WhenCounted returns value if the relation has been counted.
func WhenExistsLoaded ¶
WhenExistsLoaded returns value if the existence check has been loaded.
func WhenLoaded ¶
WhenLoaded returns value if the relation is loaded on the resource. The relation parameter is the relation name; loaded reports whether the relation has been loaded.
func WhenNotNull ¶
WhenNotNull returns value if it is non-nil, otherwise a MissingValue.
func WhenPivotLoaded ¶
WhenPivotLoaded returns value if the pivot data is loaded for the given table.
func WhenPivotLoadedAs ¶
WhenPivotLoadedAs returns value if the pivot data is loaded under the given accessor.
func WithoutWrapping ¶
func WithoutWrapping()
WithoutWrapping sends the resource map at the top level, with no wrapper key.
It changes every resource in the process. JsonResponseBuilder.WithoutWrapping is the same choice for one response.
Types ¶
type AnonymousResourceCollection ¶
type AnonymousResourceCollection struct {
ResourceCollection
}
AnonymousResourceCollection is a ResourceCollection that also records the name of the resource type it was built from, and that is all it adds.
It exists for the ordinary index action: a handler returning a list of resources has no collection type of its own to name, but something still has to carry the wrapping and the pagination metadata for the list. Collection returns one of these, and a caller who wants the collection named declares their own type instead.
func Collection ¶
func Collection(resources []JsonResource) *AnonymousResourceCollection
Collection is an anonymous collection of the resources, which is what a controller returns for an index action.
func NewAnonymousResourceCollection ¶
func NewAnonymousResourceCollection(resources []JsonResource, collects string) *AnonymousResourceCollection
NewAnonymousResourceCollection creates an AnonymousResourceCollection.
func (*AnonymousResourceCollection) PreserveKeys ¶
func (c *AnonymousResourceCollection) PreserveKeys(preserve bool) *AnonymousResourceCollection
PreserveKeys sets whether array keys should be preserved.
type Arrayable ¶
Arrayable is what a wrapped value implements when it knows how to present itself as a map. Resource.ToArray looks for it before falling back to encoding/json, so a model that implements it decides exactly which fields reach the response instead of having them read off its struct tags.
type JsonResource ¶
type JsonResource = hhttp.JsonResource
JsonResource is the interface that resource types implement. Types that implement it can be serialized to JSON responses with conditional field inclusion and wrapping.
ToArray returns the resource attributes by name; MissingValue entries are filtered out during serialization. With returns additional data to include at the top level of the response alongside the data key.
It is an alias and not a second declaration. The contract is declared in the package this one imports, because the handler-facing encoder there takes it too and cannot import this package back; one name for it in each package and two identical declarations would be one method away from being two contracts.
func CollectsResources ¶
func CollectsResources(resource any) JsonResource
CollectsResources is a helper to wrap a single resource or a slice.
type JsonResponseBuilder ¶
type JsonResponseBuilder struct {
// contains filtered or unexported fields
}
JsonResponseBuilder builds a JSON response from a resource.
func NewJsonResponse ¶
func NewJsonResponse(resource JsonResource) *JsonResponseBuilder
NewJsonResponse creates a JsonResponseBuilder for the given resource.
func (*JsonResponseBuilder) Additional ¶
func (b *JsonResponseBuilder) Additional(data map[string]any) *JsonResponseBuilder
Additional adds top-level metadata.
func (*JsonResponseBuilder) Build ¶
func (b *JsonResponseBuilder) Build() ([]byte, error)
Build builds the JSON byte response.
func (*JsonResponseBuilder) Status ¶
func (b *JsonResponseBuilder) Status(code int) *JsonResponseBuilder
Status sets the HTTP status code.
func (*JsonResponseBuilder) ToHTTPResponse ¶
func (b *JsonResponseBuilder) ToHTTPResponse() *http.Response
ToHTTPResponse builds an *http.Response (useful for testing).
func (*JsonResponseBuilder) WithWrap ¶
func (b *JsonResponseBuilder) WithWrap(key string) *JsonResponseBuilder
WithWrap sets a custom wrapper key.
func (*JsonResponseBuilder) WithoutWrapping ¶
func (b *JsonResponseBuilder) WithoutWrapping() *JsonResponseBuilder
WithoutWrapping removes the data wrapper, returning the resource data directly at the top level.
type MergeValue ¶
type MergeValue struct {
Data any
}
MergeValue wraps a value that should be merged into the parent map rather than nested as a separate key.
type MissingValue ¶
type MissingValue struct{}
MissingValue represents a value that should be omitted from the response.
func (MissingValue) IsMissing ¶
func (m MissingValue) IsMissing() bool
IsMissing always returns true for MissingValue.
type PaginatedResourceResponse ¶
type PaginatedResourceResponse struct {
Collection *ResourceCollection
Page int
PerPage int
Total int
LastPage int
}
PaginatedResourceResponse wraps a collection with pagination metadata.
func NewPaginatedResourceResponse ¶
func NewPaginatedResourceResponse(collection *ResourceCollection, page, perPage, total int) *PaginatedResourceResponse
NewPaginatedResourceResponse creates a PaginatedResourceResponse.
func (*PaginatedResourceResponse) ToArray ¶
func (p *PaginatedResourceResponse) ToArray() map[string]any
ToArray returns the paginated data with links and meta.
type PotentiallyMissing ¶
type PotentiallyMissing interface {
IsMissing() bool
}
PotentiallyMissing is the interface that wraps the IsMissing method.
Values that implement PotentiallyMissing are filtered out of JSON responses when IsMissing returns true.
type Resource ¶
type Resource struct {
// Resource is the thing being dressed.
Resource any
// WithData is what goes alongside the data key.
WithData map[string]any
// AdditionalData is what the caller added on the way out.
AdditionalData map[string]any
}
Resource is one model dressed for one response.
An application either embeds Resource and shadows ToArray, or implements the JsonResource interface on its own type. Either way it goes into NewJsonResponse.
func (*Resource) Additional ¶
Additional sets metadata to add to the response.
func (*Resource) GetRouteKey ¶
GetRouteKey forwards to the wrapped value when it is routable, nil when it is not.
func (*Resource) GetRouteKeyName ¶
GetRouteKeyName forwards to the wrapped value when it is routable, empty when it is not.
func (*Resource) JsonSerialize ¶
JsonSerialize is an alias for Resolve.
func (*Resource) ResolveChildRouteBinding ¶
ResolveChildRouteBinding always returns ErrNotRouteBindable.
func (*Resource) ResolveResourceData ¶
ResolveResourceData is an alias for ToAttributes.
func (*Resource) ResolveRouteBinding ¶
ResolveRouteBinding always returns ErrNotRouteBindable.
func (*Resource) Response ¶
func (r *Resource) Response() (*hhttp.JsonResponse, error)
Response is an alias for ToResponse.
func (*Resource) ToArray ¶
ToArray is the resource as a map.
A wrapped value that is a map or an Arrayable is taken as is; anything else goes through encoding/json, which is the same set of fields the response would have carried anyway.
func (*Resource) ToAttributes ¶
ToAttributes is the resource's attributes.
A Go type that wants a shortcut shadows ToArray directly; this is the fallback, and calls ToArray.
func (*Resource) ToPrettyJson ¶
ToPrettyJson is the indented JSON encoding of Resolve.
func (*Resource) ToResponse ¶
func (r *Resource) ToResponse() (*hhttp.JsonResponse, error)
ToResponse builds the resource into a *hhttp.JsonResponse, calling WithResponse on the way out.
func (*Resource) WithResponse ¶
func (r *Resource) WithResponse(response *hhttp.JsonResponse)
WithResponse is the hook a resource overrides to touch the response on its way out.
It does nothing here. A type embedding Resource shadows it, and calls the response methods it wants.
type ResourceCollection ¶
type ResourceCollection struct {
Resources []JsonResource
PreserveKeys bool
// contains filtered or unexported fields
}
ResourceCollection represents a collection of JsonResources.
func NewResourceCollection ¶
func NewResourceCollection(resources []JsonResource) *ResourceCollection
NewResourceCollection creates a ResourceCollection.
func (*ResourceCollection) Collects ¶
func (c *ResourceCollection) Collects() string
Collects returns the name of the resource class being collected.
func (*ResourceCollection) Count ¶
func (c *ResourceCollection) Count() int
Count returns the number of resources in the collection.
func (*ResourceCollection) GetIterator ¶
func (c *ResourceCollection) GetIterator() iter.Seq[JsonResource]
GetIterator is the resources in the collection, in order.
func (*ResourceCollection) PreserveQuery ¶
func (c *ResourceCollection) PreserveQuery() *ResourceCollection
PreserveQuery keeps every query string parameter of the current request on the pagination links.
func (*ResourceCollection) QueryParameters ¶
func (c *ResourceCollection) QueryParameters() (map[string]string, bool)
QueryParameters reports what ResourceCollection.PreserveQuery and ResourceCollection.WithQuery left behind: the parameters to put on the pagination links, and whether every parameter of the current request goes on them instead.
It exists because PaginatedResourceResponse needs to read this state from outside the package, and exporting the fields directly would be a second way to set what the two methods above set.
func (*ResourceCollection) ToArray ¶
func (c *ResourceCollection) ToArray() map[string]any
ToArray implements JsonResource.
func (*ResourceCollection) With ¶
func (c *ResourceCollection) With() map[string]any
With implements JsonResource.
func (*ResourceCollection) WithQuery ¶
func (c *ResourceCollection) WithQuery(query map[string]string) *ResourceCollection
WithQuery sets the query string parameters that should be on the pagination links, and only those.
type UrlRoutable ¶
type UrlRoutable interface {
// GetRouteKey is the value that identifies the resource in a route.
GetRouteKey() any
// GetRouteKeyName is the name GetRouteKey's value goes by in a route.
GetRouteKeyName() string
}
UrlRoutable is what a wrapped value implements when a URL segment can identify it: it reports the key that does the identifying and the name that key goes by in a route.
Resource.GetRouteKey and Resource.GetRouteKeyName forward to the wrapped value when it implements this, and answer empty when it does not. A resource is never routable itself -- Resource.ResolveRouteBinding always fails with ErrNotRouteBindable -- so what a resource can do is repeat the identity of the model it dresses, and no more.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package json holds the concrete builders and response types that compose with the interfaces in the parent package hesape/http/resources.
|
Package json holds the concrete builders and response types that compose with the interfaces in the parent package hesape/http/resources. |
|
Package jsonapi provides the resource types and helpers for building JSON:API-compliant responses, including sparse fieldsets, included resources, and relationship resolution.
|
Package jsonapi provides the resource types and helpers for building JSON:API-compliant responses, including sparse fieldsets, included resources, and relationship resolution. |