Top Level Namespace
Defined in:
Macro Summary
-
caridina_use_json_discriminator(mapping, fallback = nil)
JSON::Serializable::use_json_discriminator
on steroids.
Macro Detail
macro caridina_use_json_discriminator(mapping, fallback = nil)
#
JSON::Serializable::use_json_discriminator
on steroids.
It supports looking at many fields to discriminate the type, and case use nested fields. If no known discriminator value is found, it use the fallback type if any or raise an error.
Many types can be given for a discriminator, using an array. In this case the first one deserializing without error is returned.
The mapping should be order by priority, in case many discriminator values are found, higher priority last.
For example:
struct Event
include JSON::Serializable
caridina_use_json_discriminator(
{
["type", "name"] => {"A": EventA, "B": EventB},
"event_type" => {"A": EventA, "C": EventC, "AC": [EventA, EventC]},
}
)
struct Type
include JSON::Serializable
getter name : String
end
getter type : Type
getter event_type : String
end
Event.from_json(%(
{
"type": {"name": "A"},
...
}
)) # => EventA(…)
Event.from_json(%(
{
"event_type": "C",
...
}
)) # => EventC(…)
Event.from_json(%(
{
"event_type": "AC",
...
}
)) # => EventA, or if it fails to deserialize it to EventA then EventC
You MUST use an array when using a nested field as a discriminator field. There is no limit on the level of nesting.
If many discriminator fields match, the last one with a known value will be used.
Event.from(%(
{
"type": {"name": "unknown"},
"event_type": "C"
}
)) # => EventC(…)
Event.from(%(
{
"type": {"name": "A"},
"event_type": "unknown"
}
)) # => EventA(…)
# "event_type" is read first, but in the mapping ["type", "name"] came last so
# it has priority.
Event.from(%(
{
"event_type": "C",
"type": {"name": "A"}
}
)) # => EventA(…)