Reputation: 109
I have a decoder that currently works as desired, but I made an update and now need to pass two values into the initFilter
function, as opposed to just passing in the view.
The JSON has a new "filter" string field and I'd like to generate a specific type based on that value.
Here is the decoder for the new field:
filterTypeDecoder : Json.Decode.Decoder FilterType
filterTypeDecoder =
Json.Decode.string
|> Json.Decode.andThen
(\s ->
case s of
"filter1" ->
Json.Decode.succeed (DefaultFilter)
"edited" ->
Json.Decode.succeed (EditedFilter)
_ ->
Json.Decode.fail ("unknown filter: " ++ s)
)
Here is where I'm decoding the testModel
TestDecoder.decoder today
|> Json.Decode.andThen
(\( tester, errors ) ->
Json.Decode.succeed testModel
|> Pipeline.hardcoded tester
|> Pipeline.required "view"
(viewDecoder
|> Json.Decode.map
(initFilter tester DefaultFilter)
)
|> Pipeline.hardcoded errors
So this, as it's written currently works. The problem is, I'm providing DefaultFilter directly instead of decoding the "filter" field to figure out what it actually should be. The issue is, I'm not certain how to go about passing multiple values in via pipeline.
My first thought was to decode it separately use let to set the value of filter at the start, but then I would be decoding the same JSON twice which doesn't seem correct.
Is there a way to decode and pipe in filter to the same place that I'm piping the view? If I'm not being 100% clear, let me know...still struggle to understand elm decoding.
Upvotes: 1
Views: 378
Reputation: 36375
You can use Json.Decode.andThen
to use different decoders based on a value within the JSON itself.
First off, let's move the existing decoding of "view"
into its own function to avoid extraneous indentation:
viewFilterDecoder tester =
viewDecoder
|> Json.Decode.map
(initFilter tester DefaultFilter)
Now the decoding of "view"
looks like this:
|> Pipeline.required "view" (viewFilterDecoder tester)
Now you can update the definition of viewFilterDecoder
to first decode the "filter"
value and then (andThen
) use that filter value in the subsequent call to initFilter
:
viewFilterDecoder tester =
Json.Decode.field "filter" filterTypeDecoder
|> Json.Decode.andThen
(\filter -> viewDecoder
|> Json.Decode.map
(initFilter tester filter)
)
Upvotes: 2