Snapi
Section 5
Serializer
Serializer
Responsibilities
Converts response into Collection+JSON
Collection+JSON
Collection+JSON is a JSON-based read/write hypermedia-type designed to support management and querying of simple collections.
It uses a JSON structure to contains things like collections, refs, templates, queries, and commands.
https://github.com/collection-json/spec
include magic
class ContactApp < BaseApp
include Omicron.curation(ContactCurator)
include Omicron.serialization(ContactSerializer)
get "/contacts" do
pipe(default_response, :through => [
:serialize
])
end
get "/contacts/search" do
response = curate(artifact, :action => :search)
serialize(response)
end
end
We use the include magic to
inject serialize into the app.
class Response
include Virtus.value_object
values do
attribute :status, Integer, :default => 200
attribute :headers, Hash, :default => {}
attribute :collection, Array, :default => []
attribute :original_collection, Array, :default => []
attribute :page_information, Hash
attribute :error_message, String
end
end
include magic
Omicron.serialization takes the response and will return one of three things:
- Errors if response.error_message
- "" if no response.no_content?
- Call serialize on Serializer and return JSON
class ContactApp < BaseApp
include Omicron.serialization(ContactSerializer)
get "/contacts/search" do
response = curate(artifact, :action => :search)
serialize(response)
end
end
Scribe
All serializers inherit from Scribe which deals with the details of serialization. This allows you to only need a few functions in your serializer.
- search_url
- base_collection
- as_item
Serializer
class ContactSerializer < Scribe
private
def search_url(*args)
search_contacts_url(*args)
end
def base_collection
...
end
def as_item(object)
...
end
end
search_url
class ContactSerializer < Scribe
private
def search_url(*args)
search_contacts_url(*args)
end
end
base_collection
Returned for every request. Contains:
-
version -- the current version of the api
-
href -- href of this collection
-
rel -- unique identifier
-
template -- for creating/updating
-
links -- associated links
-
queries -- list of queries
-
commands -- list of commands
class ContactSerializer < Scribe
private
def base_collection
{
collection: {
version: API_VERSION,
href: contacts_url,
rel: "contacts",
template: {
data: [
{name: "label", value: nil},
{name: "type", value: Contact.type}
]
},
links: [
{rel: "contact_email_addresses", href: contact_email_addresses_url},
{rel: "self", href: request_url}
],
queries: [
{
rel: "search",
href: search_contacts_url,
data: [
{name: "team_id", value: nil},
{name: "can_receive_push_notifications", value: nil}
]
}
],
commands: [
{
rel: "create_bulk_contacts",
href: create_bulk_contacts_contacts_url,
data: [
{name: "team_id", value: nil},]
]
}
]
}
}
end
end
as_item
Called for every item in response.collection.
-
href -- href of this collection
-
data -- data for the item
-
links -- associated links
class ContactSerializer < Scribe
private
def as_item(object)
{
href: contact_url(object.id),
data: [
{name: "id", value: object.id},
{name: "type", value: object.type},
{name: "address_city", value: object.address_city},
{name: "address_country", value: object.address_country},
{name: "address_state", value: object.address_state},
{name: "address_street1", value: object.address_street1},
{name: "address_street2", value: object.address_street2},
{name: "address_zip", value: object.address_zip}
{name: "created_at", value: object.created_at, type: "DateTime"},
{name: "updated_at", value: object.updated_at, type: "DateTime"},
],
links: [
{
rel: "contact_email_addresses",
href: search_contact_email_addresses_url(:contact_id => object.id)
},
{
rel: "contact_phone_numbers",
href: search_contact_phone_numbers_url(:contact_id => object.id)
},
{rel: "member", href: member_url(object.member_id)},
]
}
end
end
{
"collection": {
"version": "3.454.0",
"href": "http://localhost:3000/contacts",
"rel": "contacts",
"template": {
"data": [
{
"name": "label",
"value": null
},
{
"name": "address_street1",
"value": null
},
...
{
"name": "type",
"value": "contact"
}
]
},
"links": [
{
"rel": "contact_email_addresses",
"href": "http://localhost:3000/contact_email_addresses"
},
....
{
"rel": "self",
"href": "http://localhost:3000/contacts"
}
],
"queries": [
{
"rel": "search",
"href": "http://localhost:3000/contacts/search",
"data": [
{
"name": "team_id",
"value": null
},
]
}
]
}
}
/contacts
{
"collection": {
"version": "3.454.0",
"href": "http://localhost:3000/contacts",
"rel": "contacts",
"template": {
...
},
"links": [
....
],
"queries": [
...
],
"items": [
{
"href": "http://localhost:3000/contacts/1",
"data": [
{
"name": "id",
"value": 1
},
{
"name": "type",
"value": "contact"
},
{
"name": "member_id",
"value": 63
},
{
"name": "created_at",
"value": "2017-05-10T17:28:05Z",
"type": "DateTime"
},
],
"links": [
{
"rel": "contact_email_addresses",
"href": "http://localhost:3000/contact_email_addresses/search?contact_id=1"
},
],
"rel": "contact-1"
}
]
}
}
/contacts/1
Serializer
Responsibilities
-
Converts response into Collection JSON
https://github.com/collection-json/spec
Thank you!
Snapi Section 05 Serializer
By Dustin McCraw
Snapi Section 05 Serializer
- 798