2015-09-14 14 views
17

mam te dane przy użyciu formatu http://jsonapi.org/:Elm: Jak dekodować dane z JSON API

{ 
    "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 
      } 
     } 
    ] 
} 

Mam modele jak:

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

type alias Collection = List Model 

chcę dekodowania JSON do kolekcji, ale nie wiem jak.

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 = 
    ? 

Jak mogę zaimplementować dekoder? Dzięki

Odpowiedz

22

N.B. Json.Decode docs

Spróbuj tego:

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)) 

Najtrudniejsze korzysta stringToInt włączyć pola ciągów do liczb całkowitych. Podążyłem za przykładem API pod względem tego, co jest int i co to jest ciąg znaków. Mamy szczęście, że String.toInt zwraca Result zgodnie z oczekiwaniami customDecoder, ale jest wystarczająco dużo elastyczności, aby uzyskać nieco bardziej wyrafinowane i zaakceptować oba. Zwykle używałbyś tego rodzaju rzeczy pod numer map; customDecoder jest zasadniczo map dla funkcji, które mogą zawieść.

Inną sztuczką było użycie Decode.at, aby dostać się do obiektu podrzędnego attributes.

+0

Mogę być przydatny, jeśli wyjaśnisz, jak zmapować wartość do wyniku. –

+0

OP zapytał tylko o wdrożenie dekodera. Aby uzyskać wynik, wywołaj 'Json.Decode.decodeString' lub' decodeValue'. – mgold

+2

Decode.object5 jest teraz Decode.map5 – madnight