2017-02-17 29 views
4

Учитывая следующий JSON:Decode JSON в Элм Может быть

[ 
    { 
    "id": 0, 
    "name": "Item 1", 
    "desc": "The first item" 
    }, 
    { 
    "id": 1, 
    "name": "Item 2" 
    } 
] 

Как вы расшифровать, что в следующей модели:

type alias Model = 
    { id : Int 
    , name : String 
    , desc : Maybe String 
    } 

ответ

13

Brian Hicks имеет ряд должностей на JSON декодеров, вы, вероятно, хотите конкретно посмотреть на Adding New Fields to Your JSON Decoder (который обрабатывает сценарий, в котором вы можете или не можете получить поле из объекта JSON).

Для начала, вы, вероятно, захотите использовать elm-decode-pipeline package. Затем вы можете использовать optional function, чтобы заявить, что вашего поля desc может не быть. Как указывает Брайан в статье, вы можете использовать декодер maybe от the core Json.Decode package, но он будет производить Nothing для любой ошибки, а не только null. Там есть a nullable декодер, который вы также можете рассмотреть, если вы не хотите использовать модуль конвейера.

Ваш декодер может выглядеть примерно так:

modelDecoder : Decoder Model 
modelDecoder = 
    decode Model 
     |> required "id" int 
     |> required "name" string 
     |> optional "desc" (Json.map Just string) Nothing 

Here's a live example on Ellie.

+0

После того, как я отправил свой вопрос, Гуглинг привел меня к записи Брайана Хикса на декодерах JSON. Я был рад увидеть ваш ответ, когда вернусь. Рад найти хороший источник, это полезно и для других. –

+0

В вашей последней строке, я думаю, вы хотите '(Json.map Just string)' в отличие от 'Json.map Just int ''. –

+0

Спасибо, я обновил его с помощью 'string' и примера Ellie. Надеюсь, поможет! – bdukes

2

Брайана Хикса "Adding New Fields to Your JSON Decoder" пост помог мне развить следующее. Для рабочего примера см Ellie

import Html exposing (..) 
import Json.Decode as Decode exposing (Decoder) 
import Json.Decode.Pipeline as JP 
import String 

type alias Item = 
    { id : Int 
    , name : String 
    , desc : Maybe String 
    } 


main = 
    Decode.decodeString (Decode.list itemDecoder) payload 
     |> toString 
     |> String.append "JSON " 
     |> text 


itemDecoder : Decoder Item 
itemDecoder = 
    JP.decode Item 
     |> JP.required "id" Decode.int 
     |> JP.required "name" Decode.string 
     |> JP.optional "desc" (Decode.map Just Decode.string) Nothing 
5

Так что если вы ищете для решения нулевой зависимости, которая не требует Json.Decode.Pipeline.

import Json.Decode as Decode exposing (Decoder) 


modelDecoder : Decoder Model 
modelDecoder = 
    Decode.map3 Model 
     (Decode.field "id" Decode.int) 
     (Decode.field "name" Decode.string) 
     (Decode.maybe <| Decode.field "desc" Decode.string) 

Если вы хотите сделать это с помощью Model конструктор как аппликативном функтора (потому что вам нужно больше 8 пунктов).

import Json.Decode as Decode 
import Json.Decode.Extra as Decode exposing ((|:)) 


modelDecoder : Decoder Model 
modelDecoder = 
    Decode.succeed Model 
     |: Decode.field "id" Decode.int 
     |: Decode.field "name" Decode.string 
     |: Decode.maybe (Decode.field "desc" Decode.string) 

Оба из которых может быть использован с List с с Decode.list modelDecoder. Я желаю, чтобы аппликативные функции находились в стандартной библиотеке, но для получения этих функций вам нужно будет использовать все библиотеки * -extra. Знание того, как работают аппликативные функторы, поможет вам понять, что происходит дальше, поэтому я предлагаю прочитать о них. Решение Decode Pipeline абстрагирует эту простую концепцию, но когда вы столкнулись с необходимостью для Result.andMap или любого другого из andMap, потому что для вашего модуля или DSL нет mapN, вы узнаете, как добраться до вашего решения.

+0

Вероятно, это должен быть выбранный ответ. Theres не нужно тянуть полностью отдельную зависимость только потому, что у вас есть это поведение в вашем API. Его поддерживает из коробки. – jnmandal

+0

Преимущество маршрута 'andThen' в том, что у вас есть возможность связать конкретное сообщение об ошибке, но это особенно полезно при отладке. 'andMap' должен быть технически параллелен, потому что он применим. – toastal

 Смежные вопросы

  • Нет связанных вопросов^_^