如何基于Jackson实现Map的条件化自定义序列化?
问题原因
原代码的错误出在通过BeanSerializerModifier获取的默认MapSerializer未被正确初始化,导致序列化时keySerializer为null,引发空指针异常。直接包装并调用该序列化器的serialize方法时,缺少了必要的上下文配置。
修正方案
直接为MyMap注册自定义序列化器,避免使用SerializerModifier,同时在序列化逻辑中:
- 当
name为"magic name"时,输出指定字符串; - 否则,委托Jackson的默认HashMap序列化器处理,确保所有Map序列化的细节(如键值处理、嵌套对象序列化)都能正确执行。
修正后的完整代码
import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.module.SimpleModule; import lombok.Getter; import lombok.Setter; import java.io.IOException; import java.util.HashMap; import java.util.Map; public class MapParseTest { private final ObjectMapper mapper; public MapParseTest() { mapper = new ObjectMapper(); SimpleModule module = new SimpleModule(); // 直接注册MyMap的自定义序列化器 module.addSerializer(MyMap.class, new MyMapSerializer()); mapper.registerModule(module); } public void doTest() throws IOException { MyMap map1 = new MyMap(); MyMap map2 = new MyMap(); map1.setName("shtame"); map2.setName("magic name"); map1.put("First", 1); map1.put("Second", "Two"); map1.put("Third", map2); map2.put("Eleventh", 11); map2.put("Twelfth", "12"); String result = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(map1); System.out.println(result); } public static void main(String[] args) throws IOException { MapParseTest test = new MapParseTest(); test.doTest(); } @Setter @Getter public static class MyMap extends HashMap<String, Object> { private String name; } public static class MyMapSerializer extends JsonSerializer<MyMap> { @Override public void serialize(MyMap value, JsonGenerator gen, SerializerProvider provider) throws IOException { String className = value.getName(); // 检查name是否符合条件,增加null判断避免空指针 if (className != null && className.equalsIgnoreCase("magic name")) { gen.writeString("magic string"); } else { // 委托Jackson默认的HashMap序列化器处理 JsonSerializer<Object> mapSerializer = provider.findValueSerializer(HashMap.class, null); mapSerializer.serialize(value, gen, provider); } } } }
输出结果
运行上述代码后,将得到符合期望的输出(注:HashMap不保证键值顺序,若需固定顺序可改为继承LinkedHashMap):
{ "First" : 1, "Second" : "Two", "Third" : "magic string" }
内容的提问来源于stack exchange,提问作者BUKTOP
相关产品推荐
相关产品推荐

