#json #elm #decoder
#json #elm #декодер
Вопрос:
Если у меня есть определенный помеченный тип объединения, как Shape
здесь, как бы я сконструировал для него JSON-декодер в Elm?
type alias Rectangle = { width : Int, height : Int }
type alias Circle = { radius: Int }
type Shape
= ShapeRectangle Rectangle
| ShapeCircle Circle
Ответ №1:
Учитывая, что ваш JSON выглядит как
{ "radius" : 10 }
или
{ "width" : 20, "height" : 15}
Тогда это сработает
import Json.Decode as Json exposing ((:=))
decodeShape : Json.Decoder Shape
decodeShape =
Json.oneOf
[ decodeShapeRectangle
, decodeShapeCircle
]
decodeShapeRectangle : Json.Decoder Shape
decodeShapeRectangle =
Json.map ShapeRectangle <|
Json.object2 Rectangle
("width" := Json.int)
("height" := Json.int)
decodeShapeCircle : Json.Decoder Shape
decodeShapeCircle =
Json.object1 (ShapeCircle << Circle)
("radius" := Json.int)
Пара дополнительных моментов: я часто добавляю поля «тип» и «тег», чтобы помочь устранить неоднозначность, когда у меня есть типы данных с общими именами полей. Тогда JSON выглядит следующим образом
{ "type":"shape", "tag":"circle", "radius":10 }
Также, я думаю, :=
будет заменен на field
в предстоящем выпуске 0.18.
С уважением,
Майкл
Ответ №2:
Ответ Мишеля Тома пролил здесь отличный свет.
Вы можете помечать декодированные значения с помощью Json.Decode.map
или andThen
вот так:
`andThen` x -> decode (MyTag x)
Здесь используется решение, использующее andThen
и Json.Декодировать.Конвейер
import Json.Decode exposing ( Decoder, decodeString, int, andThen, oneOf )
import Json.Decode.Pipeline exposing ( decode, required )
import Html
main =
let
decoded = decodeString decodeShape "{ "radius": 2 }"
in
case decoded of
Ok shape ->
Html.text <| toString shape
Err error ->
Html.text error
type alias Rectangle = { width : Int, height : Int }
type alias Circle = { radius: Int }
type Shape
= ShapeRectangle Rectangle
| ShapeCircle Circle
decodeShape : Decoder Shape
decodeShape =
oneOf
[ decodeRectangle `andThen` x -> decode (ShapeRectangle x)
, decodeCircle `andThen` x -> decode (ShapeCircle x)
]
decodeRectangle : Decoder Rectangle
decodeRectangle =
decode Rectangle
|> required "width" int
|> required "height" int
decodeCircle : Decoder Circle
decodeCircle =
decode Circle
|> required "radius" int