解码字符串列表
问题描述:
如何从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
}
编辑:这显然是发生在你以某种方式得到那个已经不存在的属性。
答
您确定您拥有有效的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)
答
据我了解,问题是alternateImagePaths
可能会或可能不会被包括在要解码JSON。有几种方法可以解决这个问题。
- 你可以使用
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
版本。在我看来,它使事情变得更容易阅读,并处理核心软件包遗漏的边缘案例。
@ChadGilbert你需要整个JSON对象吗? –
这是实际的json吗?品牌没有尾随逗号,而alternateImagePaths却没有引号 –