Jackson反序列化时如何过滤Map中的指定字段?
Jackson反序列化时过滤Map特定键的几种实现方案
方案一:给Map写自定义反序列化器
这是最直接的方式,专门针对Map<String, Any>定制反序列化逻辑,解析时直接移除指定键。
先编写反序列化器代码:
class FilteredMapDeserializer : StdDeserializer<Map<String, Any>>(Map::class.java) { // 要移除的目标键,按需修改即可 private val keysToRemove = setOf("foo") override fun deserialize(parser: JsonParser, ctx: DeserializationContext): Map<String, Any> { val node = parser.codec.readTree<JsonNode>(parser) val map = mutableMapOf<String, Any>() node.fields().forEach { (key, value) -> if (!keysToRemove.contains(key)) { // 处理嵌套结构(如果有嵌套Map/数组,递归解析才能过滤深层的目标键) val deserializedValue = when { value.isObject -> ctx.readValue(value.traverse(parser.codec), Map::class.java) value.isArray -> ctx.readValue(value.traverse(parser.codec), List::class.java) value.isNumber -> value.numberValue() value.isBoolean -> value.booleanValue() else -> value.asText() } map[key] = deserializedValue } } return map } }
接着在Foo类的result字段上添加注解,指定使用这个反序列化器:
data class Foo( @JsonDeserialize(contentUsing = FilteredMapDeserializer::class) val result: List<Map<String, Any>>, )
这样Jackson在反序列化每个Map元素时,会自动移除foo键,无需手动处理。
方案二:用Converter做后置过滤
如果不想写完整的反序列化器,可以用Converter实现:先让Jackson正常解析JSON为Map,再通过Converter过滤掉指定键,代码更简洁。
编写Converter代码:
class MapKeyFilterConverter : Converter<Map<String, Any>, Map<String, Any>> { private val keysToRemove = setOf("foo") override fun convert(value: Map<String, Any>): Map<String, Any> { // 基础过滤逻辑,若有嵌套Map,需添加递归处理(参考方案一的嵌套处理代码) return value.filterKeys { !keysToRemove.contains(it) } } override fun getInputType(typeFactory: TypeFactory): JavaType { return typeFactory.constructMapType(Map::class.java, String::class.java, Any::class.java) } override fun getOutputType(typeFactory: TypeFactory): JavaType { return getInputType(typeFactory) } }
然后给字段配置这个Converter:
data class Foo( @JsonDeserialize(contentConverter = MapKeyFilterConverter::class) val result: List<Map<String, Any>>, )
方案三:全局注册,所有Map自动过滤
如果项目中所有Map<String, Any>都需要过滤某个键,可以全局注册反序列化器,无需给每个字段加注解:
val objectMapper = ObjectMapper().registerModule(KotlinModule()) objectMapper.registerModule(SimpleModule().apply { addDeserializer(Map::class.java, FilteredMapDeserializer()) })
之后用这个objectMapper反序列化的所有Map,都会自动移除foo键。
注意事项
- 若Map存在嵌套结构(如Map里套Map、数组),必须在代码中添加递归处理逻辑,否则深层的目标键无法被过滤。
keysToRemove集合可灵活调整,比如从配置文件读取,或做成可动态传入的参数。
内容的提问来源于stack exchange,提问作者pixel
相关产品推荐
相关产品推荐

