2015-09-14 10 views
17

Ich habe diese Daten mit http://jsonapi.org/ Format:Elm: Wie man Daten von JSON API dekodieren

{ 
    "data": [ 
     { 
      "type": "prospect", 
      "id": "1", 
      "attributes": { 
       "provider_user_id": "1", 
       "provider": "facebook", 
       "name": "Julia", 
       "invitation_id": 25 
      } 
     }, 
     { 
      "type": "prospect", 
      "id": "2", 
      "attributes": { 
       "provider_user_id": "2", 
       "provider": "facebook", 
       "name": "Sam", 
       "invitation_id": 23 
      } 
     } 
    ] 
} 

ich meine Modelle wie haben:

type alias Model = { 
    id: Int, 
    invitation: Int, 
    name: String, 
    provider: String, 
    provider_user_id: Int 
} 

type alias Collection = List Model 

ich die json in eine Sammlung entschlüsseln möchten, aber ich weiß nicht wie.

fetchAll: Effects Actions.Action 
fetchAll = 
    Http.get decoder (Http.url prospectsUrl []) 
    |> Task.toResult 
    |> Task.map Actions.FetchSuccess 
    |> Effects.task 

decoder: Json.Decode.Decoder Collection 
decoder = 
    ? 

Wie implementiere ich Decoder? Danke

Antwort

22

N.B. Json.Decode docs

Try this:

import Json.Decode as Decode exposing (Decoder) 
import String 

-- <SNIP> 

stringToInt : Decoder String -> Decoder Int 
stringToInt d = 
    Decode.customDecoder d String.toInt 

decoder : Decoder Model 
decoder = 
    Decode.map5 Model 
    (Decode.field "id" Decode.string |> stringToInt) 
    (Decode.at ["attributes", "invitation_id"] Decode.int) 
    (Decode.at ["attributes", "name"] Decode.string) 
    (Decode.at ["attributes", "provider"] Decode.string) 
    (Decode.at ["attributes", "provider_user_id"] Decode.string |> stringToInt) 

decoderColl : Decoder Collection 
decoderColl = 
    Decode.map identity 
    (Decode.field "data" (Decode.list decoder)) 

Der schwierige Teil stringToInt wird mit String-Felder in ganze Zahlen zu drehen. Ich habe das API Beispiel in Bezug auf was ist ein int und was ist eine Zeichenfolge gefolgt. Wir haben ein wenig Glück, dass String.toInt einen Result zurückgibt, wie von customDecoder erwartet, aber es gibt genug Flexibilität, dass Sie ein wenig anspruchsvoller werden und beide akzeptieren können. Normalerweise würden Sie map für diese Art von Sache verwenden; customDecoder ist im Wesentlichen map für Funktionen, die fehlschlagen können.

Der andere Trick war, Decode.at zu verwenden, um in das attributes untergeordnete Objekt zu gelangen.

+0

Ich könnte nützlich sein, wenn Sie auch erläutert, wie Sie einen Wert in ein Ergebnis zuordnen. –

+0

OP nur nach der Implementierung des Decoders gefragt. Um das Ergebnis zu erhalten, rufen Sie 'Json.Decode.decodeString' oder' decodeValue' auf. – mgold

+2

Decode.object5 ist jetzt Decode.map5 – madnight