Conditional JSON decoder with optional fields

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"
            )
1 Like