JSON Decoding in Elm Possible

Given the following JSON:

[ { "id": 0, "name": "Item 1", "desc": "The first item" }, { "id": 1, "name": "Item 2" } ] 

How do you decode this into the following model:

 type alias Model = { id : Int , name : String , desc : Maybe String } 
+11
source share
3 answers

Brian Hicks has a series of messages on JSON decoders, you probably want to look specifically at the Adding New Fields to Your JSON Decoder (which handles a script in which you may or may not receive a field from a JSON object).

For starters, you probably want to use the elm-decode-pipe package . You can then use the optional function to declare that the desc field may be wrong. As Brian notes in the article, you can use maybe decoder from the base Json.Decode package , but it will produce Nothing for any failure, not just null . There is a nullable decoder, which you can also consider if you do not want to use the pipeline module.

Your decoder might look something like this:

 modelDecoder : Decoder Model modelDecoder = decode Model |> required "id" int |> required "name" string |> optional "desc" (Json.map Just string) Nothing 

Here's a live example from Ally.

+17
source

Therefore, if you are looking for a solution with zero dependency that does not require Json.Decode.Pipeline .

 import Json.Decode as Decode exposing (Decoder) modelDecoder : Decoder Model modelDecoder = Decode.map3 Model (Decode.field "id" Decode.int) (Decode.field "name" Decode.string) (Decode.maybe (Decode.field "desc" Decode.string)) 

If you want to do this, use the Model constructor as an applicative functor (because you need more than 8 elements).

 import Json.Decode as Decode exposing (Decoder) import Json.Decode.Extra as Decode modelDecoder : Decoder Model modelDecoder = Decode.succeed Model |> Decode.andMap (Decode.field "id" Decode.int) |> Decode.andMap (Decode.field "name" Decode.string) |> Decode.andMap (Decode.maybe (Decode.field "desc" Decode.string)) 

Both can be used with List with Decode.list modelDecoder . I would like the applicative functions to be in the standard library, but you will need to go to all * -extra libraries to get these functions. Knowing how applicative functors work will help you better understand this, so I would suggest reading about them. Decode Pipeline's solution abstracts this simple concept, but when you Result.andMap with the need for Result.andMap or any other of andMap because there is no mapN for your module or DSL, you will know how to get to your solution.

Due to the applicability of the decoders, all fields must be processed asynchronously and in parallel with a small performance gain, and not synchronously, like andThen .

Under the hood, JSON.Decode.Pipeline uses Json.Decode.map2 (that is, andMap ), so there is no performance difference, but it uses DSL, which is slightly more "friendly".

+10
source

Brian Hicks “Adding New Fields to Your JSON Decoder” helped me develop the following. For a working example, see Ellie

 import Html exposing (..) import Json.Decode as Decode exposing (Decoder) import Json.Decode.Pipeline as JP import String type alias Item = { id : Int , name : String , desc : Maybe String } main = Decode.decodeString (Decode.list itemDecoder) payload |> toString |> String.append "JSON " |> text itemDecoder : Decoder Item itemDecoder = JP.decode Item |> JP.required "id" Decode.int |> JP.required "name" Decode.string |> JP.optional "desc" (Decode.map Just Decode.string) Nothing 
+2
source

Source: https://habr.com/ru/post/1264364/


All Articles