2016-11-09 108 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版本。在我看来,它使事情变得更容易阅读,并处理核心软件包遗漏的边缘案例。