2015-09-14 2 views
17

У меня есть эти данные, используя http://jsonapi.org/ формат:Elm: Как декодировать данные из 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 
      } 
     } 
    ] 
} 

У меня есть мои модели, как:

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

type alias Collection = List Model 

Я хочу, чтобы декодировать JSON в коллекции, но не знаю, как это сделать.

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

Как реализовать декодер? Thanks

ответ

22

N.B. Json.Decode docs

Попробуйте это:

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

Хитрость использует stringToInt превратить строковые поля в целых числах. Я следовал примеру API с точки зрения того, что такое int и что такое строка. Нам повезло немного, что String.toInt возвращает Result, как и ожидалось, customDecoder, но есть достаточная гибкость, чтобы вы могли получить немного более сложные и принять оба. Обычно вы используете map для такого рода вещей; customDecoder - это по существу map для функций, которые могут выйти из строя.

Другой прием заключался в использовании Decode.at, чтобы попасть в дочерний объект attributes.

+0

Мне было бы полезно, если бы вы также объяснили, как сопоставить значение в результате. –

+0

OP только спросил о внедрении декодера. Чтобы получить результат, вызовите 'Json.Decode.decodeString' или' decodeValue'. – mgold

+2

Decode.object5 теперь Decode.map5 – madnight