2017-09-26 3 views
0

Étant donné les types suivants:Decode imbriquée valeur JSON dans Elm (0,18)

type alias Wrapper = 
    { data : Data } 

type alias Data = 
    { name : String } 

Et le JSON suivant:

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

Comment puis-je écrire un décodeur qui me permettra de transformer une HTTP réponse dans une instance de l'alias de type Wrapper?

J'ai essayé un certain nombre d'approches en utilisant les bibliothèques de base, Json.Decode.Pipeline et Json.Decode.Extra, sans trouver de solution réalisable.

Voilà ma dernière tentative:

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

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

qui se traduit par:

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:

Cette dissolution étant un problème utilisateur final. Je était passant le décodeur correct à Http.post, mais Http.send n'appelait pas réellement la fonction enveloppant Http.post. Doh.

+1

Heureux de vous voir compris! –

Répondre

1

Vos décodeurs fonctionnent très bien contre votre entrée par exemple, mais le message d'erreur que vous obtenez me conduit à croire que vous essayez d'utiliser dataDecoder dans votre appel Http plutôt que wrapperDecoder, puisque le message d'erreur est à la recherche d'un champ nommé name.

Alors que succeed et andMappeut être utilisé pour construire votre décodeur, vous pouvez obtenir avec map:

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

wrapperDecoder : Decoder Wrapper 
wrapperDecoder = 
    Decode.map Wrapper (field "data" dataDecoder) 
+0

Merci pour la réponse et la solution de vanille. Malheureusement, je passe 'wrapperDecoder' à' Http.post'. par exemple. 'Http.post apiUrl body wrapperDecoder'. – pdoherty926

1

Comme l'a écrit Tchad Gilbert, vos décodeurs sont très bien: https://ellie-app.com/kDX99XRbta1/0

Pour doubleecheck, ajouter des annotations de type à vos décodeurs:

dataDecoder : Decoder Data 
dataDecoder = ... 

wrapperDecoder : Decoder Wrapper 
wrapperDecoder = ... 

Si vous êtes vraiment à l'aide wrapperDecoder (Http.post apiUrl body wrapperDecoder), il y a encore une possibilité pour une erreur: que vos retours d'extrémité de l'API des données avec une forme différente, quelque chose comme:

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

Pouvez-vous revérifier cela? (dans Web Inspector de Chrome, etc.)

+0

Merci pour la réponse et l'échantillon de travail! Je peux confirmer que je passe 'wrapperDecoder' à' Http.post' _et_ que mon API retourne des données dans la forme attendue. 'curl -X POST http: // localhost: 5000/utilisateurs/foo => {" données ": {" nom ":" foo "}}'. Je vais essayer de nettoyer mon code et l'ajouter à ma question pour écarter tout doute. – pdoherty926