解码 json 树结构
Decode a json tree structure
在 bs-json 库中提供了一个使用 andThen
组合器将 json 结构转换为树的示例.原始示例可以在 ML 接口文件中找到 here on github。将函数 decodeTree
从此文件复制到浏览器原因工具显示语法错误。
非常感谢任何使它起作用的指示。
我尝试将其转换为 Reason3 时出现类型错误。这是代码:
type tree('a) =
| Node('a, list(tree('a)))
| Leaf('a);
let json = {| {
"type": "node",
"value": 9
"children": [{
"type": "leaf",
"value": 5,
"children": [{
"type": "leaf",
"value": 3
}, {
"type": "leaf",
"value": 2
}]
}, {
"type": "leaf",
"value": 4
}]
} |};
let decodeTree = (decodeValue, json) =>
Json.Decode.(
field("type", string)
|> andThen(type_ =>
switch type_ {
| "node" =>
Node(
field("value", decodeValue),
field("children", children =>
children |> array(decodeTree) |> map(Array.to_list)
)
)
| "leaf" => Leaf(field("value", decodeValue))
}
)
);
let myTree = json |> Json.parseOrRaise |> decodeTree(Json.Decode.int);
这是类型错误,
This has type:
tree('a)
But somewhere wanted:
Json.Decode.decoder('b) (defined as (Js.Json.t) => 'b)
很抱歉。不完全确定那个例子发生了什么。这是一个应该有效的方法:
/* Decode a JSON tree structure */
type tree('a) =
| Node('a, list(tree('a)))
| Leaf('a);
module Decode = {
open Json.Decode;
let rec tree = decoder =>
field("type", string) |> andThen(
fun | "node" => node(decoder)
| "leaf" => leaf(decoder)
| _ => failwith("unknown node type")
)
and node = (decoder, json) =>
Node(
json |> field("value", decoder),
json |> field("children", array(tree(decoder)) |> map(Array.to_list))
)
and leaf = (decoder, json) =>
Leaf(json |> field("value", decoder));
};
let json = {| {
"type": "node",
"value": 9,
"children": [{
"type": "node",
"value": 5,
"children": [{
"type": "leaf",
"value": 3
}, {
"type": "leaf",
"value": 2
}]
}, {
"type": "leaf",
"value": 4
}]
} |};
let myTree =
json |> Json.parseOrRaise
|> Decode.tree(Json.Decode.int);
编辑:您所遇到的具体错误是由于 andThen
需要解码器,但给出的是 tree('a)
(Node
或Leaf
)。将它变成解码器所需要做的就是添加一个 json 参数,您将把它传递给字段解码器:
|> andThen((type_, json) =>
switch type_ {
| "node" =>
Node(
json |> field("value", decodeValue),
json |> field("children", children =>
children |> array(decodeTree) |> map(Array.to_list)
)
)
| "leaf" => json |> Leaf(field("value", decodeValue))
}
)
在 bs-json 库中提供了一个使用 andThen
组合器将 json 结构转换为树的示例.原始示例可以在 ML 接口文件中找到 here on github。将函数 decodeTree
从此文件复制到浏览器原因工具显示语法错误。
非常感谢任何使它起作用的指示。
我尝试将其转换为 Reason3 时出现类型错误。这是代码:
type tree('a) =
| Node('a, list(tree('a)))
| Leaf('a);
let json = {| {
"type": "node",
"value": 9
"children": [{
"type": "leaf",
"value": 5,
"children": [{
"type": "leaf",
"value": 3
}, {
"type": "leaf",
"value": 2
}]
}, {
"type": "leaf",
"value": 4
}]
} |};
let decodeTree = (decodeValue, json) =>
Json.Decode.(
field("type", string)
|> andThen(type_ =>
switch type_ {
| "node" =>
Node(
field("value", decodeValue),
field("children", children =>
children |> array(decodeTree) |> map(Array.to_list)
)
)
| "leaf" => Leaf(field("value", decodeValue))
}
)
);
let myTree = json |> Json.parseOrRaise |> decodeTree(Json.Decode.int);
这是类型错误,
This has type:
tree('a)
But somewhere wanted:
Json.Decode.decoder('b) (defined as (Js.Json.t) => 'b)
很抱歉。不完全确定那个例子发生了什么。这是一个应该有效的方法:
/* Decode a JSON tree structure */
type tree('a) =
| Node('a, list(tree('a)))
| Leaf('a);
module Decode = {
open Json.Decode;
let rec tree = decoder =>
field("type", string) |> andThen(
fun | "node" => node(decoder)
| "leaf" => leaf(decoder)
| _ => failwith("unknown node type")
)
and node = (decoder, json) =>
Node(
json |> field("value", decoder),
json |> field("children", array(tree(decoder)) |> map(Array.to_list))
)
and leaf = (decoder, json) =>
Leaf(json |> field("value", decoder));
};
let json = {| {
"type": "node",
"value": 9,
"children": [{
"type": "node",
"value": 5,
"children": [{
"type": "leaf",
"value": 3
}, {
"type": "leaf",
"value": 2
}]
}, {
"type": "leaf",
"value": 4
}]
} |};
let myTree =
json |> Json.parseOrRaise
|> Decode.tree(Json.Decode.int);
编辑:您所遇到的具体错误是由于 andThen
需要解码器,但给出的是 tree('a)
(Node
或Leaf
)。将它变成解码器所需要做的就是添加一个 json 参数,您将把它传递给字段解码器:
|> andThen((type_, json) =>
switch type_ {
| "node" =>
Node(
json |> field("value", decodeValue),
json |> field("children", children =>
children |> array(decodeTree) |> map(Array.to_list)
)
)
| "leaf" => json |> Leaf(field("value", decodeValue))
}
)