轻量实用的XML与JSON/对象互转工具类(Jackson实现)
在日常开发中,XML与JSON、Java对象之间的转换是高频需求,比如接口对接、数据解析等场景。本文将分享一个基于Jackson框架实现的轻量工具类,支持多输入源、无日志依赖、兼容JDK8+,同时解决了版本兼容和异常处理等常见问题,适合作为基础工具嵌入各类项目。
一、工具类核心特性
- 无日志依赖:纯基础工具实现,不引入额外日志框架,轻量无冗余
- 功能全面:支持XML字符串/文件/输入流与JSON、Java对象的双向转换
- 灵活配置:支持JSON格式化输出开关,兼容JDK8 LocalDateTime等日期类型
- 版本兼容:解决Jackson不同版本间的特性差异(如WRITE_XML_DECLARATION常量兼容)
- 异常友好:自定义转换异常,错误信息清晰,便于问题定位
- 线程安全:Jackson映射器采用静态单例模式,线程安全且性能优异
二、完整工具类实现
java
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模块版本必须一致:
xml
<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
java
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 {
// 默认格式化输出JSON
String 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
// 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请求)
java
// 模拟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、支持更多输入源),可以基于现有代码轻松扩展。工具类的方法命名规范、注释清晰,上手成本极低,推荐在实际项目中使用。