I want to decode a JSON array of payload objects into List Payload
where each Payload
is a custom type:
type Payload
= PayloadP1 P1
| PayloadP2 P2
After decoding PayloadP1
and PayloadP2
using decoders below how do I decode Payload
?
type alias P1 =
{ id : Int
, st : String
}
type alias P2 =
{ id : Int
, s1 : String
, s2 : String
}
type Payload
= PayloadP1 P1
| PayloadP2 P2
type alias PayloadQueue = List Payload
decodeP1 : Jd.Decoder P1
decodeP1 =
Jd.map2 P1
(Jd.field "id" Jd.int)
(Jd.field "st" Jd.string)
decodeP2 : Jd.Decoder P2
decodeP2 =
Jd.map3 P2
(Jd.field "id" Jd.int)
(Jd.field "p1" Jd.string)
(Jd.field "p2" Jd.string)
decodePayload =
Jd.field ".type" Jd.string
|> Jd.andThen decodePayload_
{-
decodePayload_ : String -> Jd.Decoder Payload
decodePayload_ ptype =
case ptype of
"P1" -> decodeP1
"P2" -> decodeP2
-}
json_str = """[
{".type" : "P1", "id" : 1, "st" : "st"},
{".type" : "P2", "id" : 2, "p1" : "p1", "p2" : "p2"},
]"""
CodePudding user response:
You need to wrap P1
and P2
in PayloadP1
and PayloadP2
respectively in order to return a common type from each branch, which you can do using map
. Then you also need to account for the possibility that the type
field is neither P1
or P2
. In that case you can either provide a default or return an error using fail
. I've done the latter below.
decodePayload_ : String -> Jd.Decoder Payload
decodePayload_ ptype =
case ptype of
"P1" -> decodeP1 |> Jd.map PayloadP1
"P2" -> decodeP2 |> Jd.map PayloadP2
_ -> Jd.fail "invalid type"