我有一个树对象结构,需要进行序列化,并且我希望每次能够使用jackson(或任何其他库-我打开)基于参数来控制序列化的深度。
我的课是这样的:
class Node {
...
private String id;
private Node child;
...
}
这是我想根据深度级别获得的2个序列化json的示例
深度级别设置为3
{
"id": "A",
"child": {
"id": "B",
"child": {
"id": "C",
"child": {}
}
}
}
深度级别设置为2
{
"id": "A",
"child": {
"id": "B",
"child": {}
}
}
有什么方法可以控制递归对象中序列化的深度?
谢谢
您需要实现自定义序列化程序,在其中需要计算已经处理的Node
对象的数量。对于每个序列化过程,我们需要在max depth
每次Node
发现类时提供值并递减值。示例实现:
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.fasterxml.jackson.databind.SerializationConfig;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.BeanSerializer;
import com.fasterxml.jackson.databind.ser.BeanSerializerModifier;
import com.fasterxml.jackson.databind.ser.std.BeanSerializerBase;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicInteger;
public class JsonApp {
public static void main(String[] args) throws IOException {
Node nodeD = new Node("D", null);
Node nodeC = new Node("C", nodeD);
Node nodeB = new Node("B", nodeC);
Node nodeA = new Node("A", nodeB);
for (int i = 0; i < 4; i++) {
System.out.println("Depth: " + i);
System.out.println(serialiseWithDepth(nodeA, i));
}
}
private static ObjectMapper mapper = JsonMapper.builder()
.enable(SerializationFeature.INDENT_OUTPUT)
.addModule(createNodeModule())
.build();
private static String serialiseWithDepth(Node node, int maxDepth) throws JsonProcessingException {
ObjectWriter writer = mapper.writerFor(Node.class)
.withAttribute(NodeDepthBeanSerializer.DEPTH_KEY, new AtomicInteger(maxDepth));
return writer.writeValueAsString(node);
}
private static SimpleModule createNodeModule() {
SimpleModule nodeModule = new SimpleModule("NodeModule");
nodeModule.setSerializerModifier(new BeanSerializerModifier() {
@Override
public JsonSerializer<?> modifySerializer(SerializationConfig config, BeanDescription beanDesc, JsonSerializer<?> serializer) {
if (beanDesc.getBeanClass() == Node.class) {
return new NodeDepthBeanSerializer((BeanSerializerBase) serializer);
}
return super.modifySerializer(config, beanDesc, serializer);
}
});
return nodeModule;
}
}
class NodeDepthBeanSerializer extends BeanSerializer {
public static final String DEPTH_KEY = "maxDepthSize";
public NodeDepthBeanSerializer(BeanSerializerBase src) {
super(src);
}
@Override
protected void serializeFields(Object bean, JsonGenerator gen, SerializerProvider provider) throws IOException {
AtomicInteger depth = (AtomicInteger) provider.getAttribute(DEPTH_KEY);
if (depth.decrementAndGet() >= 0) {
super.serializeFields(bean, gen, provider);
}
}
}
上面的代码打印:
Depth: 0
Node{id='A', child=Node{id='B', child=Node{id='C', child=Node{id='D', child=null}}}} => 0
{ }
Depth: 1
Node{id='A', child=Node{id='B', child=Node{id='C', child=Node{id='D', child=null}}}} => 1
Node{id='B', child=Node{id='C', child=Node{id='D', child=null}}} => 0
{
"id" : "A",
"child" : { }
}
Depth: 2
Node{id='A', child=Node{id='B', child=Node{id='C', child=Node{id='D', child=null}}}} => 2
Node{id='B', child=Node{id='C', child=Node{id='D', child=null}}} => 1
Node{id='C', child=Node{id='D', child=null}} => 0
{
"id" : "A",
"child" : {
"id" : "B",
"child" : { }
}
}
Depth: 3
Node{id='A', child=Node{id='B', child=Node{id='C', child=Node{id='D', child=null}}}} => 3
Node{id='B', child=Node{id='C', child=Node{id='D', child=null}}} => 2
Node{id='C', child=Node{id='D', child=null}} => 1
Node{id='D', child=null} => 0
{
"id" : "A",
"child" : {
"id" : "B",
"child" : {
"id" : "C",
"child" : { }
}
}
}
问题内容: 我有一个杰克逊问题。 有没有一种方法可以反序列化可能具有两种类型的属性,对于某些对象,它看起来像这样 然后对于其他人则显示为空数组,即 任何帮助表示赞赏! 谢谢! 问题答案: Jackson目前没有内置配置来自动处理这种特殊情况,因此必须进行自定义反序列化处理。 以下是这种自定义反序列化的外观示例。 (您可以使用DeserializationConfig.Feature.ACCEPT_
问题内容: 这是我的Java代码,用于反序列化,我正在尝试将json字符串转换为java对象。为此,我使用了以下代码: 和我的product.java类 我收到以下错误。 帮我解决这个问题 问题答案: 似乎您正在尝试从JSON读取一个实际描述数组的对象。Java对象使用花括号映射到JSON对象,但是您的JSON实际上以方括号指定一个数组开始。 您实际拥有的是一个。为了描述泛型类型,由于Java的类
问题内容: 我有一个实体: 然后我有一个控制器,其目的是检索书籍,我的问题是,流派字段包含在控制器的json响应中。有什么办法可以排除杰克逊序列化对象时延迟加载的那些字段? 这是我的ObjectMapper的配置: 谢谢! 我不能将其标记为JsonIgnore,因为它将永远在序列化框中。有时候,我将需要随书一起检索体裁,然后在查询中使用“获取联接”,因此它不会为null。 问题答案: 您可以使用J
问题内容: 我有一个有时看起来像这样的对象: 有时看起来像这样: 这些类如下所示: 第一种情况是第二种情况的简写。我想总是反序列化为第二种情况。 此外- 这是我们代码中非常常见的模式,因此我希望能够以通用方式进行序列化,因为与上述类似的其他类具有将String用作语法糖的相同模式。更复杂的对象。 我以为使用它的代码看起来像这样 如何编写可同时处理两种情况的自定义解串器(或其他模块)? 问题答案:
有没有办法让Jackson序列化某个流对象(并在之后关闭)?这样地: 使现代化 澄清:我想流式传输内容,而不仅仅是将其序列化到单个String对象。
我在一个文件中有以下 JSON 当我使用Jackson将其反序列化为Java对象时,我得到以下错误 我正在使用以下代码 object mapper mapper = new object mapper(); 我已经为初始数组使用了类型引用,但如何将类型引用用于对象EnrolledEnrolment内的hashmap。 当它尝试解析第二个数组时抛出错误?有什么想法吗? 谢谢