Nesting structures in a response
Introduction
Flappi allows rich responses to be returned that model any kind of backend data.
This uses the objects
, object
and field
methods in Flappi::Definition
to shape the result data from the query.
Returning a simple hash object
If our query returns a single object, e.g:
{
name: 'Stilton',
soft: false,
cheese_type: :blue
}
then we can format it into a JSON response simply using the build/field
methods:
build do
field :name
field :soft, type: BOOLEAN
field :cheese_type
end
Returning a list of objects
For a query that returns a list of objects, e.g:
[
{ name: 'Stilton', soft: false, cheese_type: :blue },
{ name: 'Cheddar', soft: false, cheese_type: :regular },
]
we use the objects
method to format it:
build do
objects :cheeses do
field :name
end
end
This selects the name field, so we get:
{
"cheeses":
[
{ "name": "Stilton" },
{ "name": "Cheddar" }
]
}
Nesting an object
You can also nest an object. If we now have a query that returns a nested hash:
{
name: 'Stilton',
soft: false,
cheese_type: :blue,
package: { weight_grams: 1000, price: 34.32 }
}
we can use object
to format the data
build do
objects :cheeses do
field :name
field :soft, type: BOOLEAN
field :cheese_type
object name: package, type: Package do
field :weight, source: :weight_grams, type: Integer
field :price, type: BigDecimal
end
end
end
which will produce:
{
"name":"Stilton",
"soft":false,
"cheese_type":"blue",
"package":{
"weight":1000,
"price":34.32
}
}
Note that:
- We can use
name: :blah
or just:blah
as the first parameter to specify the field name tofield
,object
andobjects
- The
source
parameter lets us change a name from the query result to the generated JSON. - The
type: Package
names the nested type in the documentation, but doesn't affect the generated JSON (which doesn't have named types).
We can also use inline_always
to pull a nested object into the parent as inline fields, like this:
build do
objects :cheeses do
field :name
field :soft, type: BOOLEAN
field :cheese_type
object inline_always: true do
field :weight, source: :weight_grams, type: Integer
field :price, type: BigDecimal
end
end
end
produces
{
"name":"Stilton",
"soft":false,
"cheese_type":"blue",
"weight":1000,
"price":34.32
}
Notice that you either specify a name or inline_always
.
Nesting an array
You can easily nest arrays using objects
. Assuming we now have multiple packages:
{
name: 'Stilton',
soft: false,
cheese_type: :blue,
packages: [
{ weight_grams: 1000, price: 34.32 },
{ weight_grams: 250, price: 9.15 }
]
}
we can use objects
like this:
build do
objects :cheeses do
field :name
field :soft, type: BOOLEAN
field :cheese_type
objects name: packages do
field :weight, source: :weight_grams, type: Integer
field :price, type: BigDecimal
end
end
end
which will produce:
{
"name":"Stilton",
"soft":false,
"cheese_type":"blue",
"packages": [
{ "weight":1000, "price":34.32 },
{ "weight":250, "price":9.15 }
]
}
Generating a hash from an array
You may have an input array and want to produce a hash. This can be achieved with the hashed
option on objects
.
build do
objects :cheeses, hashed: true do
hash_key :name
field :soft
field :cheese_type
end
end
The hash_key
extracts the hash key from the data, producing:
{
"cheeses": {
"Stilton": { "soft":false, "cheese_type":"blue" },
"Cheddar": { "soft":false, "cheese_type":"regular" },
}
}