Java Record XML反序列化报错:No fallback setter/field定义问题求助
Jackson 2.18.0 Java Record XML反序列化报错:No fallback setter/field defined for creator property
使用Jackson 2.18.0处理Java Record的XML反序列化时抛出InvalidDefinitionException,提示No fallback setter/field defined for creator property 'accesslevel',相关代码及异常信息如下:
测试代码
var xml = """ <person> <accesslevels> <accesslevel>Level1</accesslevel> <accesslevel>Level2</accesslevel> </accesslevels> </person> """.trim(); var mapper = new XmlMapper(); Person person = mapper.readValue(xml, Person.class);
Person Record定义
public record Person( @JacksonXmlElementWrapper(useWrapping = false) @JacksonXmlProperty(localName = "accesslevels") List<AccessLevel> accessLevels ) { }
AccessLevel Record定义
public record AccessLevel( @JacksonXmlProperty(localName = "accesslevel") String accessLevel ) { }
异常信息
Exception in thread "main" com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No fallback setter/field defined for creator property 'accesslevel' (of `com.example.person.AccessLevel`) (through reference chain: com.example.person.Person["accesslevels"]->java.util.ArrayList[0]-> com.example.person.AccessLevel["accesslevel"]) at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67) at com.fasterxml.jackson.databind.deser.CreatorProperty._reportMissingSetter(CreatorProperty.java:358) at com.fasterxml.jackson.databind.deser.CreatorProperty._verifySetter(CreatorProperty.java:341) at com.fasterxml.jackson.databind.deser.CreatorProperty.deserializeAndSet(CreatorProperty.java:270) at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:273) at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:472) at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1497) at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:348) at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:185) at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer._deserializeFromArray(CollectionDeserializer.java:361) at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:246) at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:30) at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:543) at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeWithErrorWrapping(BeanDeserializer.java:578) at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:447) at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1497) at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:348) at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:185) at com.fasterxml.jackson.dataformat.xml.deser.WrapperHandlingDeserializer.deserialize(WrapperHandlingDeserializer.java:122) at com.fasterxml.jackson.dataformat.xml.deser.XmlDeserializationContext.readRootValue(XmlDeserializationContext.java:104) at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4917) at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3860) at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3828) at com.example.Main.main(Main.java:18)
解决思路
1. 修正AccessLevel的注解映射
XML中的<accesslevel>是直接包含文本内容的元素,而非嵌套对象。之前用@JacksonXmlProperty会让Jackson误以为要映射子元素,导致找不到对应的属性。需要改用@JacksonXmlText标记该字段是XML元素的文本内容:
public record AccessLevel( @JacksonXmlText String accessLevel ) { }
2. 调整Person的集合映射注解
原来的注解组合错误,@JacksonXmlElementWrapper(useWrapping = false)会关闭集合的外层包裹,但XML里明确有<accesslevels>作为外层容器。正确的配置是用@JacksonXmlElementWrapper指定外层容器名,@JacksonXmlProperty指定集合元素对应的XML标签:
public record Person( @JacksonXmlElementWrapper(localName = "accesslevels") @JacksonXmlProperty(localName = "accesslevel") List<AccessLevel> accessLevels ) { }
3. 验证修改
调整两个Record的注解后,运行测试代码即可正常完成XML反序列化,将<accesslevels>下的多个<accesslevel>元素映射为List<AccessLevel>。
内容的提问来源于stack exchange,提问作者Philipp Grigoryev
相关产品推荐
相关产品推荐

