0

0

Jackson XML 反序列化深度指南:处理列表类型数据的常见陷阱与解决方案

DDD

DDD

发布时间:2025-09-26 11:24:34

|

531人浏览过

|

来源于php中文网

原创

Jackson XML 反序列化深度指南:处理列表类型数据的常见陷阱与解决方案

本文探讨Jackson XML反序列化过程中,针对列表类型数据(如List)出现的MismatchedInputException和no String-argument constructor错误。核心问题在于Jackson默认无法正确识别XML中的列表结构,将其误解为单个字符串值。解决方案是利用@JacksonXmlElementWrapper(useWrapping = false)和@JacksonXmlProperty注解,明确指定XML元素的包装方式和名称映射,确保Jackson能正确解析嵌套的列表数据,从而实现XML到Java对象的顺利转换。

Jackson XML反序列化概述

jackson是一个功能强大的java库,用于处理json和xml数据。通过jackson-dataformat-xml模块,jackson能够方便地将xml字符串或文件反序列化为java对象,或将java对象序列化为xml。然而,在处理复杂的xml结构,特别是包含列表(list)类型数据时,可能会遇到一些挑战,需要借助特定的注解来指导jackson的解析行为。

列表类型数据反序列化常见问题:MismatchedInputException

当尝试将一个包含嵌套列表的XML文件反序列化为Java对象时,如果未正确配置,Jackson可能会抛出com.fasterxml.jackson.databind.exc.MismatchedInputException异常,并伴随“Cannot construct instance of YourBean (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('...')”的错误信息。

示例场景:

假设有以下Java数据传输对象(DTO):

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import java.util.List;

@JsonIgnoreProperties(ignoreUnknown = true)
@Getter @Setter @NoArgsConstructor
public class FINSTABean {
    @JsonProperty("STA_VER")
    String STA_VER;
    @JsonProperty("FINSTA03")
    List FINSTA03BeanList; // 期望解析为列表
}

@JsonIgnoreProperties(ignoreUnknown = true)
@Getter @Setter @NoArgsConstructor
public class FINSTA03Bean {
    @JsonProperty("S28_CISLO_VYPISU")
    String S28_CISLO_VYPISU;
    String S25_CISLO_UCTU; // 假设此字段在XML中存在,但未显式注解
}

以及对应的XML数据片段:



    01.0000
    
        10
    
    
        20
    

当使用XmlMapper尝试反序列化时:

XmlMapper xmlMapper = new XmlMapper();
FINSTABean bean = xmlMapper.readValue(file, FINSTABean.class);

可能会遇到如下错误:

Caused by: com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `com.lelifin.alfa.parsers.csob_xml.FINSTA03Bean` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('10')
 at [Source: (File); line: 5, column: 29] (through reference chain: com.lelifin.alfa.parsers.csob_xml.FINSTABean["FINSTA03"]->java.util.ArrayList[0])

这个错误表明Jackson尝试将XML中的元素的内容(例如10)直接反序列化为一个FINSTA03Bean对象,而不是将其识别为一个包含FINSTA03Bean对象的列表。由于FINSTA03Bean没有接受单个字符串参数的构造函数或工厂方法,导致反序列化失败。

问题根源:Jackson对XML列表结构的默认处理

Jackson在处理XML时,对于集合类型的字段,默认行为是期望有一个包装元素(wrapper element)来包含列表中的所有项。例如,如果XML结构是:

 
    ...
    ...

而我们的XML中元素直接作为父元素的子元素重复出现,并没有一个额外的包装元素来明确表示这是一个列表。在这种情况下,Jackson会误将第一个元素视为一个独立的、非列表的字段,并尝试将其内容(例如10)作为一个字符串值来构建FINSTA03Bean,从而引发MismatchedInputException。

知了zKnown
知了zKnown

知了zKnown:致力于信息降噪 / 阅读提效的个人知识助手。

下载

解决方案:使用@JacksonXmlElementWrapper和@JacksonXmlProperty

为了正确指导Jackson处理这种扁平化的列表结构,我们需要使用jackson-dataformat-xml提供的特定注解:@JacksonXmlElementWrapper和@JacksonXmlProperty。

  1. @JacksonXmlElementWrapper(useWrapping = false) 这个注解用于指示Jackson如何处理集合或数组类型的字段。当useWrapping设置为false时,它告诉Jackson该集合的元素不是由一个额外的包装XML元素所包裹,而是直接作为父元素的子元素出现。这正是我们当前XML结构所需要的。

  2. @JacksonXmlProperty(localName = "...")@JacksonXmlProperty是Jackson XML模块特有的注解,用于将Java对象的字段映射到XML元素或属性。它类似于@JsonProperty,但专为XML设计,提供了更多XML相关的控制。localName属性用于指定XML元素的名称。

修正后的DTO代码:

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import java.util.List;

@JsonIgnoreProperties(ignoreUnknown = true)
@Getter @Setter @NoArgsConstructor
public class FINSTABean {
    @JacksonXmlProperty(localName = "STA_VER") // 使用JacksonXmlProperty映射XML元素名
    String STA_VER;

    // 关键修正:
    // 1. @JacksonXmlProperty(localName = "FINSTA03"):将Java字段FINSTA03BeanList映射到XML元素FINSTA03。
    // 2. @JacksonXmlElementWrapper(useWrapping = false):指示FINSTA03BeanList的元素不是由一个额外的包装元素包裹,
    //    而是FINSTA03元素本身就代表列表中的一个项。
    @JacksonXmlProperty(localName = "FINSTA03")
    @JacksonXmlElementWrapper(useWrapping = false)
    List FINSTA03BeanList;
}

@JsonIgnoreProperties(ignoreUnknown = true) // 仍然保留,忽略XML中Java对象未定义的字段
@Getter @Setter @NoArgsConstructor
public class FINSTA03Bean {
    @JacksonXmlProperty(localName = "S28_CISLO_VYPISU")
    String S28_CISLO_VYPISU;
    @JacksonXmlProperty(localName = "S25_CISLO_UCTU") // 如果XML中存在此元素,也应明确映射
    String S25_CISLO_UCTU;
}

通过上述修改,Jackson现在能够正确地识别FINSTA03BeanList字段对应的XML结构。它会知道元素并不是一个单一的字符串值,而是列表中的一个对象实例,并且会逐个解析所有同名的元素,并将它们收集到FINSTA03BeanList中。

注意事项与最佳实践

  • @JsonProperty vs. @JacksonXmlProperty: 尽管@JsonProperty在某些情况下也能用于XML映射,但@JacksonXmlProperty是Jackson XML模块提供的更专业、更强大的注解,建议在处理XML时优先使用它,尤其是在需要精细控制XML元素或属性映射时。
  • useWrapping = true 的场景: 如果XML结构中确实存在一个包装元素,例如:
    
        ...
        ...
    

    那么在FINSTABean中,FINSTA03BeanList字段应该这样注解:

    @JacksonXmlElementWrapper(localName = "FINSTA03List") // 包装元素名称
    @JacksonXmlProperty(localName = "FINSTA03") // 列表项元素名称
    List FINSTA03BeanList;

    此时,useWrapping默认为true,或者可以显式设置为true。

  • 忽略未知属性: @JsonIgnoreProperties(ignoreUnknown = true) 是一个非常有用的注解,它指示Jackson在反序列化时忽略XML中存在但Java对象中没有对应字段的元素或属性,这可以提高代码的健壮性。
  • Lombok集成: @Getter, @Setter, @NoArgsConstructor等Lombok注解与Jackson完美兼容,它们在编译时生成了必要的getter/setter方法和无参构造函数,满足Jackson反序列化的要求。
  • XML编码: XML文件头部的encoding="windows-1250"指定了字符编码。在Java中读取文件时,确保使用正确的编码方式,例如new InputStreamReader(new FileInputStream(file), "windows-1250"),以避免乱码问题。

总结

在Jackson XML反序列化过程中,处理列表类型数据是一个常见的陷阱。MismatchedInputException通常是由于Jackson未能正确识别XML中的列表结构导致的。通过巧妙地运用@JacksonXmlElementWrapper和@JacksonXmlProperty这两个Jackson XML模块特有的注解,我们可以精确地指导Jackson如何解析复杂的XML结构,特别是当列表元素没有显式包装器时,使用@JacksonXmlElementWrapper(useWrapping = false)能够有效解决问题。理解并正确应用这些注解,是实现高效、健壮Jackson XML数据处理的关键。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
json数据格式
json数据格式

JSON是一种轻量级的数据交换格式。本专题为大家带来json数据格式相关文章,帮助大家解决问题。

419

2023.08.07

json是什么
json是什么

JSON是一种轻量级的数据交换格式,具有简洁、易读、跨平台和语言的特点,JSON数据是通过键值对的方式进行组织,其中键是字符串,值可以是字符串、数值、布尔值、数组、对象或者null,在Web开发、数据交换和配置文件等方面得到广泛应用。本专题为大家提供json相关的文章、下载、课程内容,供大家免费下载体验。

535

2023.08.23

jquery怎么操作json
jquery怎么操作json

操作的方法有:1、“$.parseJSON(jsonString)”2、“$.getJSON(url, data, success)”;3、“$.each(obj, callback)”;4、“$.ajax()”。更多jquery怎么操作json的详细内容,可以访问本专题下面的文章。

311

2023.10.13

go语言处理json数据方法
go语言处理json数据方法

本专题整合了go语言中处理json数据方法,阅读专题下面的文章了解更多详细内容。

77

2025.09.10

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

463

2023.08.02

pdf怎么转换成xml格式
pdf怎么转换成xml格式

将 pdf 转换为 xml 的方法:1. 使用在线转换器;2. 使用桌面软件(如 adobe acrobat、itext);3. 使用命令行工具(如 pdftoxml)。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

1901

2024.04.01

xml怎么变成word
xml怎么变成word

步骤:1. 导入 xml 文件;2. 选择 xml 结构;3. 映射 xml 元素到 word 元素;4. 生成 word 文档。提示:确保 xml 文件结构良好,并预览 word 文档以验证转换是否成功。想了解更多xml的相关内容,可以阅读本专题下面的文章。

2091

2024.08.01

xml是什么格式的文件
xml是什么格式的文件

xml是一种纯文本格式的文件。xml指的是可扩展标记语言,标准通用标记语言的子集,是一种用于标记电子文件使其具有结构性的标记语言。想了解更多相关的内容,可阅读本专题下面的相关文章。

1071

2024.11.28

clawdbot ai使用教程 保姆级clawdbot部署安装手册
clawdbot ai使用教程 保姆级clawdbot部署安装手册

Clawdbot是一个“有灵魂”的AI助手,可以帮用户清空收件箱、发送电子邮件、管理日历、办理航班值机等等,并且可以接入用户常用的任何聊天APP,所有的操作均可通过WhatsApp、Telegram等平台完成,用户只需通过对话,就能操控设备自动执行各类任务。

13

2026.01.29

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 3万人学习

C# 教程
C# 教程

共94课时 | 7.9万人学习

Java 教程
Java 教程

共578课时 | 52.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号