在没有方括号和字段名称的情况下使用 Jackson 将 Tree 转换为 Json
Converting Tree to Json using Jackson without having square braces and field names
我在 Java 中有以下树结构(-> 表示父级)
节点 A -> 节点 B
节点 B -> 节点 C
节点 C -> 节点 D
节点 C -> 节点 E
我有以下class代表树
class TreeNode{
private String name;
private List<TreeNode> children;
}
现在,当我将数据序列化为 Json 时,我希望得到以下输出。
{
"A": {
"B": {
"C": {
"D": {},
"E": {}
}
}
}
}
我已经设法使用自定义序列化程序来删除字段名称,但是,我收到的当前响应有方括号,我不确定如何删除它们。
我得到的当前输出
{
"A": [
{
"B": [
{
"C": [
{
"D": []
},
{
"E": []
}
]
}
]
}
]
}
我实现的序列化器
class TreeNodeSerializer extends JsonSerializer<TreeNode> {
@Override
public void serialize(Sample2Test.TreeNode value,
JsonGenerator gen,
SerializerProvider serializers) throws IOException, JsonProcessingException {
gen.writeStartObject();
gen.writeObjectField(value.getName(), value.getChildren());
gen.writeEndObject();
}
}
JSON(又名 JavaScript)中的方括号表示列表(又名数组)。
您没有提供序列化程序的代码,但我猜您只是添加 children - 这是一个 List
.
而不是 List
,您应该放置 Map
,其中键是 children 的名称,值是 children 的 children .当然,这只有在您的名字是唯一的情况下才有效。
核心问题就在这里
gen.writeObjectField(value.getName(), value.getChildren());
value.getChildren()
是一个 List<Node>
。所以,序列化器将它序列化为一个数组,然后返回自定义序列化器TreeNodeSerializer
序列化每个children.
不太明白你是怎么得到的
{
"D": [],
"E": []
}
因为你只写了一个键给object,所以我预计它应该是
{
"D": []
},
{
"E": []
}
相反。
要解决这个问题,您还需要实际序列化 children:
gen.writeFieldName(value.getName());
gen.writeStartObject();
for (Node child: value.getChildren()) {
gen.writeObjectField(child.getName(), child);
}
gen.writeEndObject();
但是,您现在可以看到 child 的名称出现了两次,一次是在 parent 序列化中,一次是在它自己的序列化中。
因此,您可以将它从自身中移除,但是您还需要解决根节点的问题,这意味着您需要类似包含节点 A 的根节点之类的东西。
这是有道理的,因为现在没有什么能阻止您的根 object 拥有多个密钥,除非您的结构不允许这样做。
所以,最终的方法应该是:
gen.writeStartObject();
for (Node child: value.getChildren()) {
gen.writeObjectField(child.getName(), child);
}
gen.writeEndObject();
并创建一个虚拟根节点来保存您的实际根节点
我在 Java 中有以下树结构(-> 表示父级)
节点 A -> 节点 B
节点 B -> 节点 C
节点 C -> 节点 D
节点 C -> 节点 E
我有以下class代表树
class TreeNode{
private String name;
private List<TreeNode> children;
}
现在,当我将数据序列化为 Json 时,我希望得到以下输出。
{
"A": {
"B": {
"C": {
"D": {},
"E": {}
}
}
}
}
我已经设法使用自定义序列化程序来删除字段名称,但是,我收到的当前响应有方括号,我不确定如何删除它们。
我得到的当前输出
{
"A": [
{
"B": [
{
"C": [
{
"D": []
},
{
"E": []
}
]
}
]
}
]
}
我实现的序列化器
class TreeNodeSerializer extends JsonSerializer<TreeNode> {
@Override
public void serialize(Sample2Test.TreeNode value,
JsonGenerator gen,
SerializerProvider serializers) throws IOException, JsonProcessingException {
gen.writeStartObject();
gen.writeObjectField(value.getName(), value.getChildren());
gen.writeEndObject();
}
}
JSON(又名 JavaScript)中的方括号表示列表(又名数组)。
您没有提供序列化程序的代码,但我猜您只是添加 children - 这是一个 List
.
而不是 List
,您应该放置 Map
,其中键是 children 的名称,值是 children 的 children .当然,这只有在您的名字是唯一的情况下才有效。
核心问题就在这里
gen.writeObjectField(value.getName(), value.getChildren());
value.getChildren()
是一个 List<Node>
。所以,序列化器将它序列化为一个数组,然后返回自定义序列化器TreeNodeSerializer
序列化每个children.
不太明白你是怎么得到的
{
"D": [],
"E": []
}
因为你只写了一个键给object,所以我预计它应该是
{
"D": []
},
{
"E": []
}
相反。
要解决这个问题,您还需要实际序列化 children:
gen.writeFieldName(value.getName());
gen.writeStartObject();
for (Node child: value.getChildren()) {
gen.writeObjectField(child.getName(), child);
}
gen.writeEndObject();
但是,您现在可以看到 child 的名称出现了两次,一次是在 parent 序列化中,一次是在它自己的序列化中。
因此,您可以将它从自身中移除,但是您还需要解决根节点的问题,这意味着您需要类似包含节点 A 的根节点之类的东西。
这是有道理的,因为现在没有什么能阻止您的根 object 拥有多个密钥,除非您的结构不允许这样做。
所以,最终的方法应该是:
gen.writeStartObject();
for (Node child: value.getChildren()) {
gen.writeObjectField(child.getName(), child);
}
gen.writeEndObject();
并创建一个虚拟根节点来保存您的实际根节点