如何将 JSON 数组解码为自定义类型的 Elm 列表

How to decode a JSON array into Elm list of custom types

我想将 JSON 负载对象数组解码为 List Payload,其中每个 Payload 都是自定义类型:

type Payload
     = PayloadP1 P1
     | PayloadP2 P2

使用下面的解码器解码 PayloadP1PayloadP2 后,我该如何解码 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"},
]"""

您需要将 P1P2 分别包装在 PayloadP1PayloadP2 中,以便 return 每个分支的通用类型,您可以使用 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。我在下面完成了后者。

decodePayload_ : String -> Jd.Decoder Payload
decodePayload_ ptype =
    case ptype of
        "P1" -> decodeP1 |> Jd.map PayloadP1
        "P2" -> decodeP2 |> Jd.map PayloadP2
        _ -> Jd.fail "invalid type"