0
votes

Given the following types:

type alias Wrapper =
    { data : Data }

type alias Data =
    { name : String }

And the following JSON:

{"data": {"name": "Keith"}}

How can I write a decoder which will allow me to turn an HTTP response into an instance of the Wrapper type alias?

I've tried a number of approaches using the core libraries, Json.Decode.Pipeline and Json.Decode.Extra, without finding a workable solution.

Here's my latest attempt:

dataDecoder =
    succeed Data
        |> andMap (field "name" Decode.string)

wrapperDecoder =
    succeed Wrapper
        |> andMap (field "data" dataDecoder)

Which results in:

BadPayload "Expecting an object with a field named name but instead got: {\"data\":{\"name\":\"foo\"}}" { status = { code = 200, message = "OK" }, headers = Dict.fromList [("cache-control","max-age=0, private, must-revalidate"),("content-type","application/json; charset=utf-8")], url = "http://localhost:5000//users/foo", body = "{\"data\":{\"name\":\"foo\"}}" }

EDIT:

This wound up being an end-user problem. I was passing the correct decoder to Http.post, but Http.send wasn't actually calling the function wrapping Http.post. Doh.

2
Glad to see you figured it out! - Martin Janiczek

2 Answers

1
votes

Your decoders work fine against your example input, but the error message you are getting leads me to believe you are trying to use dataDecoder in your Http call rather than wrapperDecoder, since the error message is looking for a field named name.

While succeed and andMap can be used to construct your decoder, you can get by with map:

dataDecoder : Decoder Data
dataDecoder =
    Decode.map Data (field "name" string)

wrapperDecoder : Decoder Wrapper
wrapperDecoder =
    Decode.map Wrapper (field "data" dataDecoder)
1
votes

As Chad Gilbert wrote, your decoders are fine: https://ellie-app.com/kDX99XRbta1/0

To doublecheck, add type annotations to your decoders:

dataDecoder : Decoder Data
dataDecoder = ...

wrapperDecoder : Decoder Wrapper
wrapperDecoder = ...

If you're really using wrapperDecoder (Http.post apiUrl body wrapperDecoder), there's one more possibility for an error: that your API endpoint returns data with a different shape, something like:

{"data": {"data": {"name": "foo"}}}

Can you doublecheck this? (in Chrome's Web Inspector etc.)