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
namebut 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.
-
1Glad to see you figured it out!Martin Janiczek– Martin Janiczek2017年09月26日 16:47:53 +00:00Commented Sep 26, 2017 at 16:47
2 Answers 2
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)
2 Comments
wrapperDecoder to Http.post. e.g. Http.post apiUrl body wrapperDecoder.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.)
1 Comment
wrapperDecoder to Http.post and that my API is returning data in the expected shape. curl -X POST http://localhost:5000/users/foo => {"data":{"name":"foo"}}. I will attempt to clean up my code and add it to my question to rule out any doubts.