Serialization
Representations serialize records into plain Ruby hashes.
PostRepresentation.serialize(post)
# => { id: 1, title: "Hello", body: "..." }This is the base shape. The adapter uses it internally and transforms it for HTTP responses (adding root keys, pagination, key formatting).
serialize can be used directly for audit logs, webhooks, event streams, or anywhere a stable representation of the data is needed.
Collections return an array:
PostRepresentation.serialize(posts)
# => [{ id: 1, ... }, { id: 2, ... }]Including Associations
Specific associations can be requested:
PostRepresentation.serialize(post, include: [:comments])
PostRepresentation.serialize(post, include: [:author, :comments])Context
Context data can be passed to serialization:
PostRepresentation.serialize(post, context: { current_user: current_user })Context is accessible in computed attributes:
class PostRepresentation < Apiwork::Representation::Base
attribute :can_edit, type: :boolean
def can_edit
context[:current_user]&.can_edit?(record)
end
endThe context and record accessors are available in all representation methods.
Deserialization
The opposite of serialize — transforms incoming data using decode transformers:
InvoiceRepresentation.deserialize(params[:invoice])
# => { email: "user@example.com", notes: nil }Use this for processing request payloads, webhooks, imports, or any external data that needs normalization before use.
Collections work the same way:
InvoiceRepresentation.deserialize(params[:invoices])
# => [{ email: "user@example.com" }, { email: "other@example.com" }]Nested Associations
Deserialization handles nested writes recursively:
class InvoiceRepresentation < Apiwork::Representation::Base
attribute :number, type: :string
attribute :email, decode: ->(v) { v.downcase.strip }
has_many :lines, representation: LineRepresentation
end
class LineRepresentation < Apiwork::Representation::Base
attribute :amount, decode: ->(v) { BigDecimal(v.to_s) }
endInvoiceRepresentation.deserialize({
number: 'INV-001',
email: ' USER@EXAMPLE.COM ',
lines: [{ amount: '99.99' }]
})
# => { number: 'INV-001', email: 'user@example.com', lines: [{ amount: BigDecimal('99.99') }] }Both has_one and has_many associations are deserialized using their representation's decode transformers.
INFO
Representation.deserialize() applies decode transformers. The built-in adapter's transformation of nested payload attributes (lines to lines_attributes) is part of the adapter pipeline and is not included in deserialize.
Encode & Decode Transformers
Define transformers on attributes to customize serialization and deserialization. See Encode & Decode and Empty & Nullable for details.
See also
- Representation::Base reference —
serializeanddeserializemethods