在Elm中解析JSON

Max*_*ker 4 json web elm

我想解析这样的JSON:

{ "shapes":[
{
    "shape": "circle",
    "x": "50",
    "y": "50",
    "r": "40"
},
{
    "shape": "rect",
    "x": "100",
    "y": "100",
    "width": "50",
    "height": "60"
},
]}
Run Code Online (Sandbox Code Playgroud)

这是我的榆树代码:

type alias Model =
    { input : Shape
    , saved : List Shape
    , modal1 : String
    , modal2 : String
    , modal3 : String
    , region : String
    }

type Shape
    = Circle String String String
    | Rectangle String String String String

type Msg
    = LoadJson
    | JsonLoaded (Result Http.Error (List Shape))

update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
    case msg of

    LoadJson -> 
        (model, getJson)

    JsonLoaded (Ok shapes) -> 
        ({ model | saved = shapes }, Cmd.none)

    JsonLoaded (Err _) ->
        (model, Cmd.none)

getJson =
    let
        url =
          "http://www.mywebsite.de/shapes.json"
    in
        Http.send JsonLoaded (Http.get url decoder)

decoder = 
    at ["shapes"] (list shapeDecoder)

shapeDecoder = 
    decode func 
        |> required "shape" string
        |> required "x" string
        |> required "y" string
        |> optional "r" string ""
        |> optional "width" string ""
        |> optional "height" string ""

func shape x y r width height = 
    case shape of
        "circle" ->
            Circle x y r

        "rect" ->
            Rectangle x y width height

        _ -> 
            Circle "" "" ""
Run Code Online (Sandbox Code Playgroud)

列表中被称为"已保存"的所有形状都应该列在表格中.

如果我在这个列表中写了一些元素,它们会显示在表中,但如果我试图从我的JSON中获取它们则不会.我的解码器有些问题,但我不知道是什么.

谢谢您的帮助.

fra*_*ium 5

您可以将解码器简化为此.使用oneOf我们可以尝试针对每个形状的解码器解码json.我不能对你的网站运行这个,因为那不是一个真正的网站,但你可以在这里运行这个解码器的演示https://ellie-app.com/cFrSPbrYna1/0

对你提供的json运行这个解码器,你会得到

Ok ([Circle "50" "50" "40",Rectangle "100" "100" "50" "60"])
Run Code Online (Sandbox Code Playgroud)

解码器:

import Json.Decode as Decode

decoder =
    Decode.at [ "shapes" ] (Decode.list decodeShape)


decodeShape =
    Decode.oneOf [ circleDecode, rectDecode ]


circleDecode =
    Decode.map4
        circle
        (Decode.field "shape" Decode.string)
        (Decode.field "x" Decode.string)
        (Decode.field "y" Decode.string)
        (Decode.field "r" Decode.string)


rectDecode =
    Decode.map5
        rect
        (Decode.field "shape" Decode.string)
        (Decode.field "x" Decode.string)
        (Decode.field "y" Decode.string)
        (Decode.field "width" Decode.string)
        (Decode.field "height" Decode.string)


circle shape x y r =
    -- Here you can, if you wanted to, have an assertion that the
    -- `shape` is indeed a "circle" and not something else
    -- In which case you probably want to return something like
    -- `Maybe Shape` or `MaybeCircle` instead of just a Circle.
    -- Same thing for the `rect` function below
    Circle x y r


rect shape x y w h =
    Rectangle x y w h
Run Code Online (Sandbox Code Playgroud)