轻量实用的 XML 与 JSON / 对象互转工具类(Jackson 实现)
轻量实用的XML与JSON/对象互转工具类(Jackson实现)
在日常开发中,XML与JSON、Java对象之间的转换是高频需求,比如接口对接、数据解析等场景。本文将分享一个基于Jackson框架实现的轻量工具类,支持多输入源、无日志依赖、兼容JDK8+,同时解决了版本兼容和异常处理等常见问题,适合作为基础工具嵌入各类项目。
一、工具类核心特性
- 无日志依赖:纯基础工具实现,不引入额外日志框架,轻量无冗余
- 功能全面:支持XML字符串/文件/输入流与JSON、Java对象的双向转换
- 灵活配置:支持JSON格式化输出开关,兼容JDK8 LocalDateTime等日期类型
- 版本兼容:解决Jackson不同版本间的特性差异(如WRITE_XML_DECLARATION常量兼容)
- 异常友好:自定义转换异常,错误信息清晰,便于问题定位
- 线程安全:Jackson映射器采用静态单例模式,线程安全且性能优异
二、完整工具类实现
package com.dolphin.utils;import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;/*** XML与JSON/对象互转工具类* 支持XML字符串/文件/输入流与JSON、Java对象之间的双向转换* 无日志依赖、兼容JDK8+、线程安全、版本兼容** @author: DolphinHome* @date: 2025/10/31 1:23*/
public class XmlToJsonUtils {// XML处理映射器(线程安全,单例模式)private static final XmlMapper xmlMapper;// JSON处理映射器(线程安全,单例模式)private static final ObjectMapper jsonMapper;static {// 初始化XML映射器并配置核心特性xmlMapper = new XmlMapper();configureXmlMapper(xmlMapper);// 初始化JSON映射器并配置核心特性jsonMapper = new ObjectMapper();configureJsonMapper(jsonMapper);}/*** 配置XML映射器核心特性*/private static void configureXmlMapper(XmlMapper mapper) {// 忽略未知属性,提高转换容错性mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);// 注册JDK8日期时间模块,支持LocalDateTime/LocalDate等类型mapper.registerModule(new JavaTimeModule());// 允许空Bean序列化,避免无字段类转换失败mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);// 兼容不同Jackson版本:尝试设置XML声明忽略(无则忽略)try {SerializationFeature feature = SerializationFeature.valueOf("WRITE_XML_DECLARATION");mapper.configure(feature, false);} catch (IllegalArgumentException e) {// 低版本Jackson不支持该特性,直接忽略}}/*** 配置JSON映射器核心特性*/private static void configureJsonMapper(ObjectMapper mapper) {// 忽略未知属性,避免JSON字段与对象不匹配时失败mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);// 支持JDK8日期时间类型序列化/反序列化mapper.registerModule(new JavaTimeModule());// 默认开启JSON格式化输出(可通过参数关闭)mapper.configure(SerializationFeature.INDENT_OUTPUT, true);// 日期时间以ISO格式输出(如2025-10-31T10:00:00),而非时间戳mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);}// ------------------------------ XML转JSON核心方法 ------------------------------/*** XML字符串转JSON字符串(默认格式化输出)* @param xml 待转换的XML字符串* @return 格式化后的JSON字符串* @throws ConversionException 转换失败时抛出*/public static String xmlToJson(String xml) {return xmlToJson(xml, true);}/*** XML字符串转JSON字符串(支持格式化开关)* @param xml 待转换的XML字符串* @param prettyPrint 是否格式化输出(true=带缩进,false=紧凑格式)* @return 转换后的JSON字符串* @throws ConversionException 转换失败时抛出*/public static String xmlToJson(String xml, boolean prettyPrint) {validateXmlInput(xml);try {JsonNode jsonNode = xmlMapper.readTree(xml);return prettyPrint ? jsonMapper.writerWithDefaultPrettyPrinter().writeValueAsString(jsonNode) :jsonMapper.writeValueAsString(jsonNode);} catch (JsonProcessingException e) {throw new ConversionException("XML转JSON失败: " + e.getMessage(), e);}}/*** XML文件转JSON字符串(默认格式化输出)* @param filePath XML文件绝对路径* @return 格式化后的JSON字符串* @throws ConversionException 文件读取或转换失败时抛出*/public static String xmlFileToJson(String filePath) {return xmlFileToJson(filePath, true);}/*** XML文件转JSON字符串(支持格式化开关)* @param filePath XML文件绝对路径* @param prettyPrint 是否格式化输出* @return 转换后的JSON字符串* @throws ConversionException 文件读取或转换失败时抛出*/public static String xmlFileToJson(String filePath, boolean prettyPrint) {try {// 以UTF-8编码读取文件内容String xmlContent = new String(Files.readAllBytes(Paths.get(filePath)), StandardCharsets.UTF_8);return xmlToJson(xmlContent, prettyPrint);} catch (IOException e) {throw new ConversionException("读取XML文件或转换JSON失败: " + e.getMessage(), e);}}/*** 输入流XML转JSON字符串(默认格式化输出)* @param inputStream 包含XML内容的输入流(如HTTP请求流、文件流)* @return 格式化后的JSON字符串* @throws ConversionException 流读取或转换失败时抛出*/public static String xmlStreamToJson(InputStream inputStream) {return xmlStreamToJson(inputStream, true);}/*** 输入流XML转JSON字符串(支持格式化开关)* @param inputStream 包含XML内容的输入流* @param prettyPrint 是否格式化输出* @return 转换后的JSON字符串* @throws ConversionException 流读取或转换失败时抛出*/public static String xmlStreamToJson(InputStream inputStream, boolean prettyPrint) {if (inputStream == null) {throw new ConversionException("输入流不能为null");}try {JsonNode jsonNode = xmlMapper.readTree(inputStream);return prettyPrint ? jsonMapper.writerWithDefaultPrettyPrinter().writeValueAsString(jsonNode) :jsonMapper.writeValueAsString(jsonNode);} catch (IOException e) {throw new ConversionException("从输入流转换XML到JSON失败: " + e.getMessage(), e);}}// ------------------------------ XML转Java对象核心方法 ------------------------------/*** XML字符串直接转Java对象* @param xml 待转换的XML字符串* @param clazz 目标对象的Class类型* @param <T> 目标对象泛型* @return 转换后的Java对象* @throws ConversionException 转换失败时抛出*/public static <T> T xmlToObject(String xml, Class<T> clazz) {validateXmlInput(xml);try {return xmlMapper.readValue(xml, clazz);} catch (JsonProcessingException e) {throw new ConversionException("XML转" + clazz.getSimpleName() + "失败: " + e.getMessage(), e);}}/*** XML文件直接转Java对象* @param filePath XML文件绝对路径* @param clazz 目标对象的Class类型* @param <T> 目标对象泛型* @return 转换后的Java对象* @throws ConversionException 文件读取或转换失败时抛出*/public static <T> T xmlFileToObject(String filePath, Class<T> clazz) {try {return xmlMapper.readValue(new File(filePath), clazz);} catch (IOException e) {throw new ConversionException("XML文件转" + clazz.getSimpleName() + "失败: " + e.getMessage(), e);}}// ------------------------------ 输入验证辅助方法 ------------------------------/*** 验证XML字符串输入合法性* @param xml 待验证的XML字符串* @throws ConversionException 输入为null或空字符串时抛出*/private static void validateXmlInput(String xml) {if (xml == null || xml.trim().isEmpty()) {throw new ConversionException("XML字符串不能为null或空");}}// ------------------------------ 自定义转换异常 ------------------------------/*** 转换异常封装类:统一捕获转换过程中的所有异常*/public static class ConversionException extends RuntimeException {public ConversionException(String message) {super(message);}public ConversionException(String message, Throwable cause) {super(message, cause);}}
}
三、Maven依赖配置
工具类基于Jackson框架实现,需引入以下依赖(JDK8+适用),注意所有Jackson模块版本必须一致:
<properties><!-- 统一Jackson版本(建议2.15+,兼容JDK8+且修复较多漏洞) --><jackson.version>2.17.1</jackson.version>
</properties><dependencies><!-- Jackson核心模块:JSON解析/生成基础 --><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-core</artifactId><version>${jackson.version}</version></dependency><!-- Jackson注解模块:支持@JsonProperty等注解(databind依赖) --><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-annotations</artifactId><version>${jackson.version}</version></dependency><!-- Jackson对象绑定模块:核心功能(对象↔JSON) --><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>${jackson.version}</version></dependency><!-- JDK8日期时间支持模块:必须引入,否则LocalDateTime等类型转换失败 --><dependency><groupId>com.fasterxml.jackson.datatype</groupId><artifactId>jackson-datatype-jsr310</artifactId><version>${jackson.version}</version></dependency><!-- Jackson XML支持模块:XML解析核心依赖 --><dependency><groupId>com.fasterxml.jackson.dataformat</groupId><artifactId>jackson-dataformat-xml</artifactId><version>${jackson.version}</version></dependency>
</dependencies>
依赖说明:
- 若项目已引入
spring-boot-starter-web,Spring Boot会自动依赖Jackson核心模块,此时只需指定jackson.version即可,无需重复引入 - 版本必须统一:不同版本的Jackson模块混合使用会导致类缺失、方法不兼容等问题
jackson-datatype-jsr310模块是JDK8+必备,否则LocalDateTime、LocalDate等类型无法正常序列化/反序列化
四、快速使用示例
1. XML字符串转JSON
public class TestXmlToJson {public static void main(String[] args) {// 待转换的XML字符串String xml = "<user>" +"<id>1001</id>" +"<name>张三</name>" +"<age>25</age>" +"<createTime>2025-10-31T09:30:00</createTime>" +"</user>";try {// 默认格式化输出JSONString json = XmlToJsonUtils.xmlToJson(xml);System.out.println("格式化JSON:" + json);// 紧凑格式输出JSON(无缩进)String compactJson = XmlToJsonUtils.xmlToJson(xml, false);System.out.println("紧凑JSON:" + compactJson);} catch (XmlToJsonUtils.ConversionException e) {// 异常处理(如日志记录、友好提示)e.printStackTrace();}}
}
2. XML文件转Java对象
假设存在user.xml文件,内容同上,且有对应的Java实体类:
// Java实体类
public class User {private Long id;private String name;private Integer age;private LocalDateTime createTime;// getter/setter省略
}// 转换测试
public class TestXmlToObject {public static void main(String[] args) {try {// XML文件路径(绝对路径)String filePath = "D:/data/user.xml";// 直接转换为User对象User user = XmlToJsonUtils.xmlFileToObject(filePath, User.class);System.out.println("用户ID:" + user.getId());System.out.println("创建时间:" + user.getCreateTime());} catch (XmlToJsonUtils.ConversionException e) {e.printStackTrace();}}
}
3. 输入流XML转JSON(如HTTP请求)
// 模拟HTTP请求获取XML输入流(实际场景可替换为真实请求流)
InputStream inputStream = new FileInputStream("D:/data/user.xml");try {String json = XmlToJsonUtils.xmlStreamToJson(inputStream);System.out.println("输入流转换结果:" + json);
} catch (FileNotFoundException | XmlToJsonUtils.ConversionException e) {e.printStackTrace();
} finally {// 关闭输入流(实际开发中建议用try-with-resources)inputStream.close();
}
五、注意事项
- 编码规范:工具类默认使用UTF-8编码读取文件和转换,若XML文件为其他编码(如GBK),需手动指定编码格式
- 线程安全:XmlMapper和ObjectMapper是线程安全的,无需每次转换都创建实例,工具类已通过静态单例优化
- 异常处理:所有转换异常都会封装为
ConversionException,上层调用时可统一捕获处理,无需关注底层具体异常 - 复杂XML支持:支持包含子节点、列表的复杂XML结构,转换后的JSON会保持对应的层级关系
- 空值处理:XML中的空标签会转换为JSON的
null值,Java对象中的空字段也会正常序列化
六、总结
这个工具类基于Jackson实现,兼顾了轻量性和实用性,移除了日志依赖,适合作为基础组件嵌入各类Java项目。它解决了日常开发中XML与JSON、Java对象转换的核心需求,同时处理了版本兼容、异常封装、输入验证等细节问题,让开发者无需关注底层实现,直接调用静态方法即可完成转换。
如果需要扩展功能(如JSON转XML、支持更多输入源),可以基于现有代码轻松扩展。工具类的方法命名规范、注释清晰,上手成本极低,推荐在实际项目中使用。
