我有一个树对象结构,需要进行序列化,并且我希望每次能够使用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发现类时提供值并递减值。示例实现:
Node
max depth
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" : { } } } }