枚举类上的JsonbTypeDeserializer未触发,如何使其生效?
解决JsonB枚举自定义反序列化器不触发的问题
问题核心原因
你的代码里有两个关键问题:
- 注解引用的内部类名称错误:
@JsonbTypeSerializer和@JsonbTypeDeserializer中指定的Serializer/Deserializer类不存在,实际内部类名为AddressSerializer和AddressDeserializer,导致JsonB无法加载自定义反序列化器。 - JsonB对枚举有默认序列化/反序列化逻辑,默认优先调用枚举的
valueOf方法匹配常量名称,若注解配置错误,完全不会触发自定义处理器。
修复步骤
1. 修正注解的内部类引用
将枚举类顶部的注解修改为正确的内部类路径:
@JsonbTypeSerializer(Address.AddressSerializer.class) @JsonbTypeDeserializer(Address.AddressDeserializer.class) public enum Address { // 原有代码不变 }
2. 优化反序列化器异常处理
避免异常时返回null,改为抛出标准的JsonB异常,便于排查问题:
public static final class AddressDeserializer implements JsonbDeserializer<Address> { @Override public Address deserialize(JsonParser parser, DeserializationContext ctx, Type rtType) { String value; try { value = parser.getString(); } catch (IllegalStateException ise) { throw new jakarta.json.bind.JsonbException("读取JSON值失败", ise); } for (Address b : Address.values()) { if (b.value().equals(value)) { return b; } } throw new jakarta.json.bind.JsonbException("无法识别的地址值: '" + value + "'"); } }
3. (可选)显式注册处理器
若注解方式仍不生效,可在创建Jsonb实例时直接注册序列化/反序列化器:
@Test void addressEnumTest() throws Exception { JsonbConfig config = new JsonbConfig() .withSerializer(Address.class, new Address.AddressSerializer()) .withDeserializer(Address.class, new Address.AddressDeserializer()); try (Jsonb jsonb = JsonbBuilder.create(config)) { for (Address a : Address.values()) { String json = jsonb.toJson(a); assertEquals("\"" + a.value() + "\"", json); Address result = jsonb.fromJson(json, Address.class); assertEquals(a, result); } } }
4. 替代方案:使用@JsonbCreator静态方法
如果不想依赖自定义处理器,可添加带@JsonbCreator的静态工厂方法,让JsonB直接通过该方法解析枚举:
public enum Address { MAIN_ADDRESS("Main_Address"), DELIVERY_ADDRESS("Delivery_Address"); private String value; Address(String value) { this.value = value; } // 原有方法不变 @JsonbCreator public static Address fromValue(String value) { for (Address addr : Address.values()) { if (addr.value.equals(value)) { return addr; } } throw new IllegalArgumentException("无效的地址值: " + value); } }
验证效果
修正后重新运行测试,自定义反序列化器会被正常触发,JSON值"Main_Address"和"Delivery_Address"能正确映射到对应的枚举常量。
内容的提问来源于stack exchange,提问作者Claudio Zesiger
相关产品推荐
相关产品推荐

