解码JSON,其中value可以是字符串或不同值的数组

时间:2017-06-07 05:07:15

标签: elm

关于如何用榆树解码事物的另一个问题......

所以问题是我需要解码一个可以是字符串的值,例如

public $belongsToMany = [ 'plan' =>[ 'MyPlugin\Plans\Models\Plans', 'table' => 'cls_useraccount_subscription', 'key'=>'user_id', 'otherKey' => 'plan_id', ], ];

或者它可以是2个元素的数组,其中第一个是字符串,第二个是浮点数:

"price_unknown"

对于最终的价值,我有一个类型:

["price", 50.5]

我需要转换json响应中的值。

我试图在以下几行之间使用一些东西:

type Something
  = PriceUnknown
  = Price Float

(我在这里使用decode MyString |> required "other_value" Json.Decode.string |> required "price" JD.oneOf [JD.string, JD.list (JD.oneOf [JD.string, JD.float])] |> JD.map mapper 包)

但显然它会在列表中抱怨不同的值,以及所以我被卡住了。

提前谢谢。

1 个答案:

答案 0 :(得分:3)

您非常接近,但Decoder中的所有oneOf都必须具有相同的类型。此外,解构混合列表可能是一个痛苦。这使用elm-community/json-extra来简化手动解码步骤。

myDecoder : Decoder SomethingElse
myDecoder =
    decode MyString
        |> required "other_value" Json.Decode.string
        |> required "price" priceDecoder


priceDecoder : Decoder Something
priceDecoder =
    JD.oneOf
        [ priceUnknownDecoder
        , priceKnownDecoder
        ]


priceUnknownDecoder : Decoder Something
priceUnknownDecoder =
    JD.string
        |> JD.andThen
            (\string ->
                if string == "price_unknown" then
                    JD.succeed PriceUnknown
                else
                    JD.fail "Invalid unknown price string."
            )


priceKnownDecoder : Decoder Something
priceKnownDecoder =
    listTupleDecoder
        JD.string
        JD.float
        |> JD.andThen
            (\(tag, price) ->
                if tag == "price" then
                    JD.succeed (Price price)
                else
                    JD.fail "Invalid tag string."
            )


listTupleDecoder : Decoder a -> Decoder b -> Decoder (a, b)
listTupleDecoder firstD secondD =
    JD.list JD.value
        |> JD.andThen
            (\values ->
                case values of
                    [first, second] ->
                        Result.map2
                            (,)
                            JD.decodeValue firstD first
                            JD.decodeValue secondD second
                            |> JD.Extra.fromResult

                    _ ->
                        JD.fail "There aren't two values in the list."
            )