如何使用Jackson过滤HashMap指定键并转换为JSON?
问题原因
你之前的代码无效,是因为Jackson的SimpleBeanPropertyFilter是为JavaBean的字段过滤设计的,而非Map的键。直接给ObjectMapper设置FilterProvider对Map类型的序列化完全不起作用。
Jackson实现Map键动态过滤的方案
下面是几种Jackson原生的高效实现方式,能满足你基于同一Map生成多份不同过滤规则JSON的需求:
方案1:自定义序列化修改器+ObjectWriter(推荐)
通过自定义BeanSerializerModifier拦截Map的序列化过程,动态控制哪些键需要保留。每次需要不同过滤规则时,生成对应的ObjectWriter即可,无需修改原ObjectMapper。
import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.ser.BeanSerializerModifier; import com.fasterxml.jackson.databind.ser.std.MapSerializer; import java.io.IOException; import java.util.Map; import java.util.Set; public class MapKeyFilterModifier extends BeanSerializerModifier { private final Set<String> allowedKeys; public MapKeyFilterModifier(Set<String> allowedKeys) { this.allowedKeys = allowedKeys; } @Override public JsonSerializer<?> modifyMapSerializer(SerializationConfig config, MapType valueType, BeanDescription beanDesc, JsonSerializer<?> serializer) { return new FilteredMapSerializer((MapSerializer) serializer, allowedKeys); } private static class FilteredMapSerializer extends MapSerializer { private final Set<String> allowedKeys; public FilteredMapSerializer(MapSerializer src, Set<String> allowedKeys) { super(src); this.allowedKeys = allowedKeys; } @Override public void serialize(Map<?, ?> value, JsonGenerator gen, SerializerProvider provider) throws IOException { gen.writeStartObject(); for (Map.Entry<?, ?> entry : value.entrySet()) { String key = entry.getKey().toString(); if (allowedKeys.contains(key)) { gen.writeFieldName(key); provider.defaultSerializeValue(entry.getValue(), gen); } } gen.writeEndObject(); } } }
使用方式
// 初始化原Map Map<String, String> hashMap = new HashMap<>(); hashMap.put("KEY1", "VALUE1"); hashMap.put("KEY2", "VALUE2"); hashMap.put("KEY3", "VALUE3"); ObjectMapper objectMapper = new ObjectMapper(); // 生成仅保留KEY1的JSON Set<String> filter1 = Set.of("KEY1"); ObjectWriter writer1 = objectMapper.writer() .with(new BeanSerializerModifier[]{new MapKeyFilterModifier(filter1)}); System.err.println(writer1.writeValueAsString(hashMap)); // 输出 {"KEY1":"VALUE1"} // 生成保留KEY2、KEY3的JSON Set<String> filter2 = Set.of("KEY2", "KEY3"); ObjectWriter writer2 = objectMapper.writer() .with(new BeanSerializerModifier[]{new MapKeyFilterModifier(filter2)}); System.err.println(writer2.writeValueAsString(hashMap)); // 输出 {"KEY2":"VALUE2","KEY3":"VALUE3"}
方案2:流式过滤Map(简单高效)
如果不需要严格依赖Jackson的序列化过滤机制,这种方式更直接,性能也更优:
import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; // 初始化原Map Map<String, String> hashMap = new HashMap<>(); hashMap.put("KEY1", "VALUE1"); hashMap.put("KEY2", "VALUE2"); hashMap.put("KEY3", "VALUE3"); ObjectMapper objectMapper = new ObjectMapper(); // 过滤规则1:保留KEY1 Set<String> allowed1 = Set.of("KEY1"); Map<String, String> filteredMap1 = hashMap.entrySet().stream() .filter(entry -> allowed1.contains(entry.getKey())) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); System.err.println(objectMapper.writeValueAsString(filteredMap1)); // 过滤规则2:保留KEY2、KEY3 Set<String> allowed2 = Set.of("KEY2", "KEY3"); Map<String, String> filteredMap2 = hashMap.entrySet().stream() .filter(entry -> allowed2.contains(entry.getKey())) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); System.err.println(objectMapper.writeValueAsString(filteredMap2));
总结
如果坚持使用Jackson的序列化过滤机制,方案1是最优选择——它可以基于同一Map生成任意过滤规则的JSON,且无需修改原Map数据;如果追求实现简单,方案2的流式过滤更直接高效。
内容的提问来源于stack exchange,提问作者randomgood
相关产品推荐
相关产品推荐

