attributes
attribute
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 renders: { id: 1234, name: 'My place' }
// PlaceSerializer renders: { id: 1234, name: 'My place', style: 'cabin', sleeps: 5 }
CalendarDate and DateTime attributes (even arrays of them) are automatically converted to their ISO values during serialization.
openapi
When serializing a Dream model with DreamSerializer, the OpenAPI shape of database column attributes is determined automatically (except for json and jsonb columns). You can still add an OpenAPI description if you want:
.attribute('name', { openapi: { description: 'The name of the Place' } })
With ObjectSerializer, you always need to provide the openapi option, since there's no schema to pull from. Same goes for virtual attributes on Dream models — even with DreamSerializer, virtual attributes need an explicit openapi shape:
export const PlaceSerializer = (place: Place) =>
DreamSerializer(Place, place)
.attribute('id')
.attribute('myVirtualAttribute', { openapi: ['string', 'null'] })
For json/jsonb columns, you'll need to spell out the full OpenAPI shape:
export const PlaceSerializer = (place: Place) =>
DreamSerializer(Place, place)
.attribute('id')
.attribute('myJsonAttribute', {
openapi: {
type: 'object',
properties: {
label: 'string',
value: 'decimal',
},
},
})
default
The default option provides a fallback when the attribute is null or undefined. Default values go through the same transformations as regular data (decimals get rounded, dates get converted to ISO format, etc.):
export const PlaceSerializer = (place: Place) =>
DreamSerializer(Place, place)
.attribute('id')
.attribute('name', { default: 'unnamed' })
.attribute('sleeps', { default: 0 })
as
Use the as option to rename the attribute in the output:
export const PlaceSerializer = (place: Place) =>
DreamSerializer(Place, place).attribute('id').attribute('sleeps', { as: 'accommodates' })
// renders: { id: 1234, accommodates: 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 renders: { id: 1234, rating: 4.7 }
delegatedAttribute
The delegatedAttribute method reaches into a nested object or association and pulls an attribute into the serialized output. Associations used by delegatedAttribute are automatically loaded by preloadFor:
export const PlaceSummaryForGuestsSerializer = (place: Place) =>
DreamSerializer(Place, place)
.attribute('id')
.delegatedAttribute('currentLocalizedText', 'title', { openapi: 'string' })
// A place with currentLocalizedText { title: 'Hello world' } renders:
// { id: 1234, title: 'Hello world' }
delegatedAttribute.default
All options from attribute are supported on delegatedAttribute. The default kicks in whether the association itself is null or the attribute on the association is null:
.delegatedAttribute('currentLocalizedText', 'title', {
openapi: 'string',
default: 'Untitled',
})
// A place without a currentLocalizedText, or one with { title: null }, renders:
// { id: 1234, title: 'Untitled' }
customAttribute
The customAttribute method is for arbitrary data transformation. It's especially handy for leveraging passthrough data. 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 documentation for how to set passthrough data on automatically rendered serializers.
customAttribute.flatten
When flatten: true is included, the attributes of the returned object get flattened into the parent:
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' }