Serializing Attributes
Basic Attributes
The attribute
method includes a property from your source object in the serialized output.
export const PlaceSummarySerializer = (place: Place) =>
DreamSerializer(Place, place).attribute('id').attribute('name')
export const PlaceSerializer = (place: Place) =>
PlaceSummarySerializer(place).attribute('style').attribute('sleeps')
// PlaceSummarySerializer serializes to:
// { id: 1234, name: 'My place' }
// and PlaceSerializer serializes to:
// { id: 1234, name: 'My place', style: 'cabin', sleeps: 5 }
CalendarDate and DateTime attributes (even arrays of CalendarDate and DateTime values) are automatically converted to their ISO values as part of serialization.
openapi
option
When serializing a Dream model with DreamSerializer, the OpenAPI shape of attributes corresponding to database columns is determined automatically (except for json and jsonb columns). However, you may still want to include an openapi description:
.attribute('name', { openapi: { description: 'The name of the Place' } })`
ObjectSerializer serializer attributes always requires the openapi
option.
For a virtual attribute on a Dream model, openapi
is required even for DreamSerializer:
export const PlaceSerializer = (place: Place) =>
DreamSerializer(Place, place)
.attribute('id')
.attribute('myVirtualAttribute', { openapi: ['string', 'null'] })
This example leverages OpenAPI shorthand, but the full OpenAPI shape is available for representing complex shapes, as one must do for attributes that correspond to json/jsonb columns:
export const PlaceSerializer = (place: Place) =>
DreamSerializer(Place, place)
.attribute('id')
.attribute('myJsonAttribute', {
openapi: {
type: 'object',
properties: {
label: 'string',
value: 'decimal',
},
},
})
default
option
The default
option provides a fallback value when the attribute is null
or undefined
. The default value undergoes the same transformations as regular data (e.g., decimals are rounded, dates are converted to ISO format).
export const PlaceSerializer = (place: Place) =>
DreamSerializer(Place, place)
.attribute('id')
.attribute('name', { default: 'unnamed' })
.attribute('sleeps', { default: 0 })
renaming attributes with as
Use the as
option to change the name of the attribute in the output.
export const PlaceSerializer = (place: Place) =>
DreamSerializer(Place, place).attribute('id').attribute('sleeps', { as: 'accomodates' })
// PlaceSerializer serializes to:
// { id: 1234, accomodates: 5 }
precision
Decimal values can be automatically rounded with the precision
option.
export const PlaceSerializer = (place: Place) =>
DreamSerializer(Place, place).attribute('id').attribute('rating', { precision: 1 })
// A place with rating 4.66666 would serialize to:
// { id: 1234, rating: 4.7 }
Delegated Attributes
The delegatedAttribute
method renders an attribute from a nested object into the serialized output. delegatedAttribute
attributes are automatically inspected as part of preloadFor (so when delegating to an association, that association will be automatically preloaded).
export const PlaceSummaryForGuestsSerializer = (place: Place) =>
DreamSerializer(Place, place)
.attribute('id')
.delegatedAttribute('currentLocalizedText', 'title', { openapi: 'string' })
// A place with currentLocalizedText with { title: 'Hello world' } will render:
// { id: 1234, title: 'Hello world' }
default
option
All options from the attribute
method are supported on delegatedAttribute
. On a delegated attribute, the default will be applied whether then association is null or the attribute on the association is null:
export const PlaceSummaryForGuestsSerializer = (place: Place) =>
DreamSerializer(Place, place).attribute('id').delegatedAttribute('currentLocalizedText', 'title', {
openapi: 'string',
default: 'Untitled',
})
// A place without a currentLocalizedText or a currentLocalizedText with { title: null } will render:
// { id: 1234, title: 'Untitled' }
The default
option provides a fallback value when either the target object is null
/undefined
OR when the delegated attribute itself is null
/undefined
.
Custom Attributes
customAttribute
is used for arbitrary data transformation. It is especially useful for rendering or leveraging passthrough data into the serialized output. customAttribute
always requires the openapi
option.
export const PlaceForGuestsSerializer = (place: Place, passthrough: { locale: LocalesEnum }) =>
PlaceSummaryForGuestsSerializer(place).customAttribute(
'style',
() => i18n(passthrough.locale, `places.style.${place.style}`),
{
openapi: 'string',
}
)
See the passthrough setting documentation for details on how to set passthrough data on automatically rendered serializers.
flatten
When flatten: true
is included, the attributes of the returned object are flattened into the serialized results.
const UserSerializer = (user: User) =>
DreamSerializer(User, user)
.attribute('id')
.customAttribute('profileInfo', () => ({ age: 30, city: 'Metropolis' }), {
flatten: true,
openapi: {
age: { type: 'integer' },
city: { type: 'string' },
},
})
// renders { id: 1, age: 30, city: 'Metropolis' }