Java 通用树的自定义Jackson序列化程序
假设我有一个用Java实现的参数化树,如下所示:Java 通用树的自定义Jackson序列化程序,java,json,generics,jackson,Java,Json,Generics,Jackson,假设我有一个用Java实现的参数化树,如下所示: public class Tree<E> { private static class Node { E element; List<Node> children. } Node root; //... You get the idea. } public class Tree<E> { private static class Node {
public class Tree<E> {
private static class Node {
E element;
List<Node> children.
}
Node root;
//... You get the idea.
}
public class Tree<E> {
private static class Node {
@JsonUnwrapped
E element;
List<Node> children.
}
@JsonUnwrapped
Node root;
//... You get the idea.
}
因此,最后,地理层次结构如下所示:
public class Geography extends Tree<GeoElement> {}
这种JSON呈现不好,因为它包含树和节点类中不必要的构件,即“根”和“元素”。我需要的是:
{
“名称”:“拉丁美洲”,
“类型”:“大陆”
“儿童”:[
{
“名称”:“巴西”,
“类型”:“国家”
“儿童”:[
//…巴西的州名单
]
},
{
“名称”:“阿根廷”,
“类型”:“国家”
“儿童”:[
//……阿根廷的国家名单
]
}
]
}
非常感谢您的帮助-Igor.或许可以这样使用
@JsonValue
:
public class Tree<E> {
@JsonValue
Node root;
}
公共类树{
@JsonValue
节根;
}
如果只需“展开”树即可删除
元素
类型,一种可能是更改结构,使名称和类型直接包含在每个节点中:
public class TreeGeo {
private static class Node {
String name;
String type;
List<Node> children.
}
Node root;
}
公共类树{
私有静态类节点{
字符串名;
字符串类型;
列出孩子们。
}
节根;
}
要删除
根目录
类型,我不知道。我想你可以从jsonObject中提取一个子对象,但我对Jackson知之甚少。但是,您可以给它一个更好的名称,如world
,或者通过一些字符串操作手动删除结果字符串。您最好的选择是为您的对象构建并注册一个自定义序列化程序
定义序列化程序:
public class NodeSerializer extends StdSerializer<Node> {
以及节点串行化器的内部
@Override
public void serialize(
Node node, JsonGenerator jgen, SerializerProvider provider)
throws IOException, JsonProcessingException {
jgen.writeStartObject();
jgen.writeStringField("name", node.element.name);
jgen.writeStringField("type", node.element.type);
//Process children
serializeFields(node, jgen, provider);
jgen.writeEndObject();
}
这个通用框架将允许您控制如何序列化元素。您可能还需要@JsonIgnore
节点内的元素
对象
,因为您的自定义序列化程序负责将该信息推送到生成的JSON中。网上有很多关于自定义序列化程序和重写默认JSON导出的内容
您可以使用树实现的序列化程序以类似的方式除去root
如果不想在类上注册序列化程序,也可以使用ObjectMapper
一次注册一个序列化程序:
ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addSerializer(Node.class, new NodeSerializer());
mapper.registerModule(module);
String serialized = mapper.writeValueAsString(tree);
注释方法将全局应用。这种方法允许对自定义序列化程序的使用方式/位置进行某种控制。您需要的是
用于指示属性应序列化为“展开”的注释;也就是说,如果将其序列化为JSON对象,则其属性将作为其包含对象的属性包含
将此注释添加到节点
类的树
和元素
字段的根
字段,如下所示:
public class Tree<E> {
private static class Node {
E element;
List<Node> children.
}
Node root;
//... You get the idea.
}
public class Tree<E> {
private static class Node {
@JsonUnwrapped
E element;
List<Node> children.
}
@JsonUnwrapped
Node root;
//... You get the idea.
}
谢谢你的建议,斯里尼瓦斯。它不起作用,因为我不想忽略节点,只想丢弃节点包装器。你找到解决方案了吗?如果找到了,请update@anonStaxMan提供的解决方案不起作用吗?我在类中没有根节点。节点->数据,列表结构。在这里,我必须创建一个单独的节点序列化程序,并编写递归代码来完成它,我认为这是行不通的。它只需打开外部
根对象。它不会展开元素
对象。
{
"name": "Latin America",
"type": "Continent",
"children": [{
"name": "Brazil",
"type": "Country",
"children": []
}, {
"name": "Argentina",
"type": "Country",
"children": []
}]
}