This is a really challenging data structure you have here. You’re right that andThen
won’t work. My current thought is to have multiple decoders that attempt to decode each of the meta data’s and then Json.Decode.andThen
both the type information and the collection of potential metadata fields and see if the metadata for the type was found. Something like
{
"id": 2,
"timestamp": "etc",
"type": {"id": 4, "name": "bed"},
"bed": {
// (Bed metadata goes here)
}
}
decodeData =
map5 (\id timestamp type_ maybeBed maybeChair ->
( Data I'd timestamp, type_, { bed = maybeBed, chair = maybeChair } )
)
(field "id" string)
(field "timestamp" string)
(at [ "type", "name" ] string)
(maybe (field "bed" bedMetaDecoder))
(maybe (field "chair" chairMetaDecoder))
|> andThen
(\( dataFn, type_, rec ) ->
case type_ of
"chair" ->
case rec.chair of
Just chairMeta -> success (dataFn chairMeta)
Nothing -> fail "Expected 'chair' metadata"
"bed" ->
case rec.bed of
...
_ -> fail "unknown type"
)