2016-11-09 48 views
1

如何從JSON解碼字符串列表?我有這樣的代碼,目前沒有忘記時間:解碼字符串列表

import Html exposing (..) 
import Html.App as App 
import Html.Attributes exposing (..) 
import Html.Events exposing (onInput, onClick) 
import Http 
import Json.Decode as Json exposing ((:=)) 
import Json.Decode exposing (object3) 
import Task 



main = 
    App.program 
    { view = view 
    , init = init 
    , update = update 
    , subscriptions = subscriptions 
    } 



init : (Model, Cmd Msg) 
init = 
    (Model "" { productName = "", brand = "", alternateImagePaths = [] }, Cmd.none) 


-- MODEL 

type alias Product = 
    { productName : String 
    , brand : String 
    , alternateImagePaths : List String 
    } 

type alias Model = 
    { id : String 
    , product : Product} 

-- UPDATE 


type Msg 
    = GetProduct 
    | UpdateText String 
    | FetchSucceed Product 
    | FetchFail Http.Error 


update : Msg -> Model -> (Model, Cmd Msg) 
update msg model = 
    case msg of 
    GetProduct -> 
     (model, getData model.id) 

    UpdateText text -> 
     ({ model | id = text }, Cmd.none) 

    FetchSucceed p -> 
     ({ model | product = p } , Cmd.none) 

    FetchFail _ -> 
     ({ model | id = "" }, Cmd.none) 


-- VIEW 


view : Model -> Html Msg 
view model = 
    div [] 
    [ input [ type' "text", onInput UpdateText ] [] 
    , button [ type' "button", onClick GetProduct ] [ text "Search" ] 
    , br [] [] 
    , pre [] [ text model.id ] 
    , pre [] [ text (toString model.product) ] 
    ] 


-- HTTP 


getData : String -> Cmd Msg 
getData id = 
    let 
    url = "https://localhost:3000/v2/product/" ++ id 
    in 
    Task.perform FetchFail FetchSucceed (Http.get decodeData url) 


decodeData : Json.Decoder Product 
decodeData = 
    object3 Product 
    ("productName" := Json.string) 
    ("brand" := Json.string) 
    ("alternateImagePaths" := Json.list Json.string) 


subscriptions : Model -> Sub Msg 
subscriptions model = 
    Sub.none 

如果我刪除alternateImagePaths,它擊中FetchSucceed功能,但如果我離開它,它擊中FetchFail功能。

數據結構(實際響應):

{ 
    "productName": "Men's San Francisco 49ers Design Your Own T-Shirt-", 
    "team": [ 
    "San Francisco 49ers" 
    ], 
    "brand": "Pro Line", 
    "shippingTimeFrame": 3 
} 

編輯:這顯然是發生在你以某種方式得到那個已經不存在的屬性。

+0

@ChadGilbert你需要整個JSON對象嗎? –

+0

這是實際的json嗎?品牌沒有尾隨逗號,而alternateImagePaths卻沒有引號 –

回答

1

您確定您擁有有效的JSON嗎?讓客戶端代碼使用它之前,您應該始終驗證它 。

這是小修復後的工作代碼。

import Html exposing (text) 
import Json.Decode exposing (..) 

json = """ 
{ 
    "productName": "Panthers Shirt", 
    "brand": "Nike", 
    "alternateImagePaths": ["url.com", "url2.com"], 
    "dummy": "dummyval" 
} 
""" 

main = 
    text <| toString (decodeString decodeData json) 

type alias Product = 
    { productName : String 
    , brand : String 
    , alternateImagePaths : List String 
    } 

decodeData : Decoder Product 
decodeData = 
    object3 Product 
    ("productName" := string) 
    ("brand" := string) 
    ("alternateImagePaths" := list string) 
1

據我瞭解,問題是alternateImagePaths可能會或可能不會被包括在要解碼JSON。有幾種方法可以解決這個問題。

  1. 你可以使用oneOf尋找alternateImagePaths並取得成功,如果它是什麼字符串列表。這是處理它,因爲你仍然會得到一個空列表,如果alternateImagePaths是別的東西,像一個整數快速「東經骯髒的方式:
decodeData : Json.Decoder Product 
decodeData = 
    Json.object3 Product 
     ("productName" := Json.string) 
     ("brand" := Json.string) 
     (Json.oneOf ["alternateImagePaths" := Json.list Json.string, Json.succeed []]) 
  • 您也可以使用NoRedInk/elm-decode-pipeline包,該包用optional解碼器明確處理這種情況。
  • decodeData : Json.Decoder Product 
    decodeData = 
        decode Product 
         |> required "productName" Json.string 
         |> required "brand" Json.string 
         |> optional "alternateImagePaths" (Json.list Json.string) [] 
    

    我建議使用elm-decode-pipeline版本。在我看來,它使事情變得更容易閱讀,並處理核心軟件包遺漏的邊緣案例。