
本文介绍使用 Jackson 的 @JsonFilter 注解配合 Mix-in 类,对任意 HashMap 进行动态键过滤并序列化为 JSON,支持运行时灵活指定需排除或保留的键,无需修改原始数据结构。
本文介绍使用 jackson 的 @jsonfilter 注解配合 mix-in 类,对任意 hashmap 进行动态键过滤并序列化为 json,支持运行时灵活指定需排除或保留的键,无需修改原始数据结构。
Jackson 默认将 Map 视为无结构的键值容器,不支持直接通过 @JsonFilter 对其字段(即 map 的 key)进行细粒度控制——因为 Map 本身没有 JavaBean 属性。但通过 Mix-in 类 + 全局过滤器 的组合方式,可巧妙绕过该限制,实现动态键过滤。
关键在于:为 java.lang.Object(所有对象的父类)注册一个带 @JsonFilter 的 Mix-in 类。由于 HashMap 继承自 Object,且 Jackson 在序列化 Map 时会将其视为“具有属性的实体”(每个 key 被映射为一个逻辑属性),此时全局 Filter 就能生效。
以下为完整、可运行的示例:
// Step 1: 定义空 Mix-in 类,仅声明过滤器名称
@JsonFilter("filter")
public static class DynamicMixIn {}
// Step 2: 构建待序列化的 Map
Map<String, String> data = new HashMap<>();
data.put("KEY1", "VALUE1");
data.put("KEY2", "VALUE2");
data.put("KEY3", "VALUE3");
// Step 3: 配置 ObjectMapper
ObjectMapper mapper = new ObjectMapper();
mapper.addMixIn(Object.class, DynamicMixIn.class); // 关键:将过滤器绑定到 Object
// Step 4: 动态构建过滤器(此处排除 KEY1;也可用 filterOutAllExcept 保留指定键)
FilterProvider filters = new SimpleFilterProvider()
.addFilter("filter", SimpleBeanPropertyFilter.serializeAllExcept("KEY1"));
mapper.setFilterProvider(filters);
// Step 5: 序列化 —— 输出 {"KEY2":"VALUE2","KEY3":"VALUE3"}
String json = mapper.writeValueAsString(data);
System.out.println(json);✅ 优势说明:
-
动态性强:每次调用前可重新构造
SimpleFilterProvider,传入不同 key 列表,适配多场景 JSON 输出; -
零侵入:无需为
HashMap创建包装类或 DTO,也不修改原始数据; - 高性能:避免手动遍历 Map 构建新子集,由 Jackson 底层高效处理。
⚠️ 注意事项:
-
serializeAllExcept(...)表示排除指定 key;若需仅保留某些 key,请改用filterOutAllExcept("KEY1", "KEY3"); -
addMixIn(Object.class, ...)必须在setFilterProvider(...)之前调用; - 此方案适用于 Jackson 2.7+,低版本可能存在兼容性问题;
- 若需对不同 Map 应用不同过滤策略,建议为每个策略复用独立的
ObjectMapper实例(或通过copy()创建轻量副本),避免 FilterProvider 冲突。
总结:通过 Mix-in + 全局 Filter 的设计模式,Jackson 完美支持 HashMap 的运行时键级过滤,是构建灵活 JSON API 或多视图数据导出的理想方案。


















