如何从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 :(得分: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 :(得分:1)
据我了解,问题是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 []])
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
版本。在我看来,它使事情更容易阅读,它处理核心包遗漏的这些边缘情况。