我刚刚开始与Elm合作,使用我正在研究的Rest API进行一些前端原型设计.通常,API返回可以解码的"合理"数据结构,因为键和值类型是众所周知的,但是几种资源类型返回的data条目只有具有没有预定结构的原始json.
到目前为止我读过的所有东西似乎都假设你知道你正在解码的数据的结构,而在普通的js中,相对容易循环键并反映类型以确定它们应该如何在运行时处理.我还没有看到在Elm中处理这类数据的明确路径.
例如,
{
"name":"foo",
"data": {
"bar": [{"baz":123}, "quux"]
},
...
}
Run Code Online (Sandbox Code Playgroud)
我想知道目前是否可以data用类似的东西来解析条目的值
function go(obj)
for key in keys(foo)
if foo[key] is an object
go(foo[k])
else if foo[key] is an array
map(go, foo[k])
...
Run Code Online (Sandbox Code Playgroud)
特别:
Cha*_*ert 10
是的,可以编写通用解码器.您可以先定义一个包含所有可能的Json类型的联合类型:
type JsVal
= JsString String
| JsInt Int
| JsFloat Float
| JsArray (List JsVal)
| JsObject (Dict String JsVal)
| JsNull
Run Code Online (Sandbox Code Playgroud)
现在你可以Json.Decode.oneOf尝试各种可能性.
import Json.Decode as D exposing (Decoder)
import Dict exposing (Dict)
jsValDecoder : Decoder JsVal
jsValDecoder =
D.oneOf
[ D.string |> D.andThen (D.succeed << JsString)
, D.int |> D.andThen (D.succeed << JsInt)
, D.float |> D.andThen (D.succeed << JsFloat)
, D.list (D.lazy (\_ -> jsValDecoder)) |> D.andThen (D.succeed << JsArray)
, D.dict (D.lazy (\_ -> jsValDecoder)) |> D.andThen (D.succeed << JsObject)
, D.null JsNull
]
Run Code Online (Sandbox Code Playgroud)
Json.Decode.lazy对于JsArray和JsObject构造函数是必需的,因为它们是递归定义的.
这个结构应该处理你抛出的任何东西,并且由你的程序的其余部分来决定如何处理这种灵活的类型.
编辑
正如@Tosh指出的那样,这个解码器可以通过使用map而不是andThen后面的a 来清理succeed:
jsValDecoder : Decoder JsVal
jsValDecoder =
D.oneOf
[ D.map JsString D.string
, D.map JsInt D.int
, D.map JsFloat D.float
, D.list (D.lazy (\_ -> jsValDecoder)) |> D.map JsArray
, D.dict (D.lazy (\_ -> jsValDecoder)) |> D.map JsObject
, D.null JsNull
]
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
909 次 |
| 最近记录: |