如何配置Jackson反序列化时跳过含"deleted":"true"的JSON数组元素?
解决Jackson反序列化时过滤特定条目的问题
刚好之前做过类似的需求,Jackson有几种实用的方式可以实现过滤掉"deleted":"true"条目的效果,我给你分享两个最常用的方案,都是亲测有效的:
方案一:自定义List类型的反序列化器
这个方案直接针对List的反序列化过程,逐个检查元素并过滤,逻辑直观易懂。
步骤1:定义你的实体类
首先是对应JSON结构的Item类:
public class Item { private String id; private String deleted; // 生成getter、setter方法,以及必要的构造函数 public String getId() { return id; } public void setId(String id) { this.id = id; } public String getDeleted() { return deleted; } public void setDeleted(String deleted) { this.deleted = deleted; } }
步骤2:编写自定义反序列化器
创建一个继承JsonDeserializer的类,专门处理List<Item>的反序列化:
import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class FilteredItemListDeserializer extends JsonDeserializer<List<Item>> { @Override public List<Item> deserialize(JsonParser parser, DeserializationContext context) throws IOException { ObjectMapper mapper = (ObjectMapper) parser.getCodec(); JsonNode rootNode = mapper.readTree(parser); List<Item> filteredItems = new ArrayList<>(); // 遍历JSON数组中的每个元素 if (rootNode.isArray()) { Iterator<JsonNode> elementIterator = rootNode.elements(); while (elementIterator.hasNext()) { JsonNode itemNode = elementIterator.next(); // 注意:你的deleted字段是字符串类型的"true"/"false",所以要用字符串比较 if (!"true".equals(itemNode.get("deleted").asText())) { // 将符合条件的节点转换为Item对象并加入列表 Item item = mapper.treeToValue(itemNode, Item.class); filteredItems.add(item); } } } return filteredItems; } }
步骤3:注册反序列化器并使用
在ObjectMapper中注册这个自定义反序列化器,然后就可以正常反序列化了:
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.core.type.TypeReference; public class Main { public static void main(String[] args) throws IOException { String jsonData = "[{\"id\": \"abc\", \"deleted\": \"true\"},{\"id\": \"def\", \"deleted\": \"false\"}]"; ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule(); // 为List<Item>类型注册自定义反序列化器 module.addDeserializer(new TypeReference<List<Item>>() {}, new FilteredItemListDeserializer()); mapper.registerModule(module); List<Item> result = mapper.readValue(jsonData, new TypeReference<List<Item>>() {}); // 此时result中只会包含id为def的Item对象 } }
方案二:通过BeanDeserializerModifier拦截单个对象反序列化
这个方案更灵活,它会拦截所有Item对象的反序列化过程,如果是标记为deleted的对象就返回null,再配置Jackson自动忽略集合中的null元素,适合Item可能出现在其他集合或嵌套结构中的场景。
步骤1:编写BeanDeserializerModifier
创建一个修改器类,用来替换默认的Item反序列化器:
import com.fasterxml.jackson.databind.BeanDescription; import com.fasterxml.jackson.databind.DeserializationConfig; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.deser.BeanDeserializerModifier; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonNode; import java.io.IOException; public class ItemDeserializerModifier extends BeanDeserializerModifier { @Override public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config, BeanDescription beanDesc, JsonDeserializer<?> deserializer) { // 只处理Item类的反序列化 if (beanDesc.getBeanClass() == Item.class) { return new StdDeserializer<Item>(Item.class) { @Override public Item deserialize(JsonParser parser, DeserializationContext context) throws IOException { JsonNode itemNode = parser.getCodec().readTree(parser); // 检查deleted字段,返回null表示过滤该对象 if ("true".equals(itemNode.get("deleted").asText())) { return null; } // 否则使用默认的反序列化逻辑 return ((StdDeserializer<?>) deserializer).deserialize(parser, context); } }; } return super.modifyDeserializer(config, beanDesc, deserializer); } }
步骤2:配置ObjectMapper并使用
注册修改器,同时配置Jackson忽略集合中的null元素:
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.core.type.TypeReference; public class Main { public static void main(String[] args) throws IOException { String jsonData = "[{\"id\": \"abc\", \"deleted\": \"true\"},{\"id\": \"def\", \"deleted\": \"false\"}]"; ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule(); module.setDeserializerModifier(new ItemDeserializerModifier()); mapper.registerModule(module); // 配置Jackson忽略集合中的null元素 mapper.configure(DeserializationFeature.ACCEPT_NULL_ARRAY_ELEMENTS, false); List<Item> result = mapper.readValue(jsonData, new TypeReference<List<Item>>() {}); // 同样得到只包含id为def的Item列表 } }
关键注意点
一定要注意你的deleted字段是字符串类型的"true",不是布尔值true,所以判断的时候必须用字符串相等比较,不能用itemNode.get("deleted").asBoolean(),否则会出现判断错误的情况。
内容的提问来源于stack exchange,提问作者Magesh khanna
相关产品推荐
相关产品推荐

