Java Record字段能否同时添加多个注解?
Java Record字段无法获取自定义Jackson注解的问题解决
你遇到的问题并非Java Record不能同时添加多个注解,而是Jackson对Record的注解处理逻辑和普通类存在差异:在Record中,你写在组件后的注解(如@BigDecimalScale)默认会被绑定到构造方法的参数上,而非对应的字段;而你的反序列化器如果是从字段上获取注解,自然拿不到@BigDecimalScale,导致scale参数未生效,最终得到1500而非预期的15.00。
问题根源
Java Record的组件字段是隐式生成的,你在Record组件声明时添加的注解,会被编译器自动转移到构造方法的对应参数上,而非字段本身。普通类的字段注解则直接附着在字段上,因此反序列化器在普通类中能正常获取注解,但在Record中无法通过字段拿到。
解决方案
有两种可行的修改方式:
方式一:扩展自定义注解的Target范围
修改@BigDecimalScale的@Target,添加ElementType.PARAMETER,让注解可以同时作用于字段和构造方法参数:
@Target({ ElementType.FIELD, ElementType.PARAMETER }) @Retention(RetentionPolicy.RUNTIME) public @interface BigDecimalScale { int value(); }
方式二:修改反序列化器的注解获取逻辑
在实现ContextualDeserializer时,兼容从构造方法参数和字段两种途径获取注解,示例如下:
@Override public JsonDeserializer<?> createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException { BigDecimalScale scaleAnn = null; // 优先从Record构造方法参数获取注解 if (property.getMember() instanceof ConstructorParameter) { scaleAnn = property.getMember().getAnnotation(BigDecimalScale.class); } // 从普通类字段获取注解 if (scaleAnn == null && property.getMember() instanceof Field) { scaleAnn = property.getMember().getAnnotation(BigDecimalScale.class); } // 初始化带scale参数的反序列化器实例 if (scaleAnn != null) { return new BytesToBigDecimalConverter(scaleAnn.value()); } return this; }
验证效果
修改完成后重新运行测试代码,Record的cost字段会正确解析为15.00,与普通类的输出结果一致。
Jackson从2.12版本开始支持Java Record,但注解处理需要注意这种参数/字段的差异,通过上述两种方式即可兼容Record和普通类的注解获取逻辑。
内容的提问来源于stack exchange,提问作者Crompy
相关产品推荐
相关产品推荐

