XML 自己写一个XML序列化器
在之前的XML相关内容中,我们学习了XML的基础语法、解析方式等知识点,而在实际开发中,经常需要把程序中的对象数据转换成XML格式的字符串,这个过程就是XML序列化。今天我们就自己动手实现一个简单的XML序列化器,完成对象到XML的转换功能。
XML序列化器的核心需求
我们要实现的XML序列化器需要满足以下核心需求:
- 支持将Java对象的基础属性(字符串、整数、布尔值等)转换为XML元素
- 支持处理对象的嵌套关系,也就是对象中包含其他对象的情况
- 生成的XML格式规范,包含根节点,属性名作为元素名,属性值作为元素内容
- 对特殊字符做转义处理,避免生成的XML出现语法错误
基础实现思路
实现XML序列化器的核心思路是通过反射获取对象的所有属性,然后遍历每个属性,将属性名作为XML的元素名,属性值作为元素的内容,同时递归处理属性值为对象的情况。我们还需要先处理属性值中的特殊字符,比如把<转义为<,>转义为>,&转义为&,保证生成的XML符合语法规范。
代码示例
下面是一个简单的Java版XML序列化器实现,包含特殊字符转义、属性遍历、嵌套对象处理等核心逻辑:
import java.lang.reflect.Field;
import java.util.*;
public class XmlSerializer {
// 特殊字符转义方法,避免XML语法错误
private static String escapeXml(String input) {
if (input == null) {
return "";
}
return input.replace("&", "&")
.replace("<", "<")
.replace(">", ">")
.replace("\"", """)
.replace("'", "'");
}
// 核心序列化方法,obj为要序列化的对象,rootTagName为根节点名称
public static String serialize(Object obj, String rootTagName) throws IllegalAccessException {
if (obj == null) {
return "";
}
StringBuilder xmlBuilder = new StringBuilder();
// 添加XML声明
xmlBuilder.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
// 序列化对象内容
String content = serializeObject(obj, rootTagName);
xmlBuilder.append(content);
return xmlBuilder.toString();
}
// 序列化单个对象的方法
private static String serializeObject(Object obj, String tagName) throws IllegalAccessException {
if (obj == null) {
return "<" + tagName + "/>\n";
}
StringBuilder objBuilder = new StringBuilder();
objBuilder.append("<").append(tagName).append(">\n");
// 获取对象的所有属性(包含私有属性)
Field[] fields = obj.getClass().getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
String fieldName = field.getName();
Object fieldValue = field.get(obj);
// 处理不同类型的属性值
if (fieldValue == null) {
objBuilder.append(" <").append(fieldName).append("/>\n");
} else if (isBaseType(fieldValue)) {
// 基础类型直接转换为字符串,做转义处理
String valueStr = escapeXml(String.valueOf(fieldValue));
objBuilder.append(" <").append(fieldName).append(">")
.append(valueStr)
.append("</").append(fieldName).append(">\n");
} else if (fieldValue instanceof List) {
// 处理集合类型,每个元素作为一个子节点
List<?> list = (List<?>) fieldValue;
objBuilder.append(" <").append(fieldName).append(">\n");
for (Object item : list) {
String itemXml = serializeObject(item, "item");
// 缩进处理,保证格式美观
String[] lines = itemXml.split("\n");
for (String line : lines) {
if (!line.trim().isEmpty()) {
objBuilder.append(" ").append(line).append("\n");
}
}
}
objBuilder.append(" </").append(fieldName).append(">\n");
} else {
// 嵌套对象,递归序列化
String nestedXml = serializeObject(fieldValue, fieldName);
String[] lines = nestedXml.split("\n");
for (String line : lines) {
if (!line.trim().isEmpty()) {
objBuilder.append(" ").append(line).append("\n");
}
}
}
}
objBuilder.append("</").append(tagName).append(">\n");
return objBuilder.toString();
}
// 判断是否为基础类型(字符串、基本类型及其包装类)
private static boolean isBaseType(Object obj) {
return obj instanceof String ||
obj instanceof Integer || obj instanceof int[] ||
obj instanceof Long || obj instanceof long[] ||
obj instanceof Boolean || obj instanceof boolean[] ||
obj instanceof Double || obj instanceof double[] ||
obj instanceof Float || obj instanceof float[] ||
obj instanceof Short || obj instanceof short[] ||
obj instanceof Byte || obj instanceof byte[] ||
obj instanceof Character || obj instanceof char[];
}
// 测试用的用户类
static class User {
private String name;
private int age;
private boolean vip;
private Address address;
public User(String name, int age, boolean vip, Address address) {
this.name = name;
this.age = age;
this.vip = vip;
this.address = address;
}
}
// 测试用的地址类,作为嵌套对象
static class Address {
private String city;
private String street;
public Address(String city, String street) {
this.city = city;
this.street = street;
}
}
// 测试方法
public static void main(String[] args) throws IllegalAccessException {
Address addr = new Address("北京", "朝阳区XX路");
User user = new User("张三", 25, true, addr);
String xmlResult = serialize(user, "user");
System.out.println(xmlResult);
}
}上面的代码中,我们首先实现了escapeXml方法处理特殊字符转义,避免属性值中的特殊字符破坏XML结构。然后serialize方法是入口,接收要序列化的对象和根节点名称,先拼接XML声明,再调用serializeObject方法处理对象内容。serializeObject方法通过反射获取对象的所有属性,区分基础类型、集合类型、嵌套对象三种情况分别处理,基础类型直接转字符串并转义,集合类型遍历每个元素生成子节点,嵌套对象则递归调用序列化方法。最后我们定义了User和Address两个测试类,运行测试方法后就能得到对应的XML字符串。
功能扩展方向
目前我们实现的是最基础的XML序列化器,实际使用中还可以根据需求扩展更多功能:
- 支持通过注解自定义XML元素名,比如给属性添加
@XmlElement注解指定序列化后的元素名,而不是默认使用属性名 - 支持将对象属性序列化为XML属性,而不是子元素,比如
<user age="25">这种形式 - 增加类型适配器,支持自定义特殊类型的序列化逻辑,比如日期类型可以按照指定格式转换为字符串
- 处理循环引用问题,避免对象之间相互引用导致递归栈溢出
通过自己实现XML序列化器,我们能更清晰地理解XML序列化的底层逻辑,也能根据项目需求灵活定制序列化规则,比直接使用第三方库更贴合特定场景的需要。
XML序列化器Java反射对象转XML自定义序列化嵌套对象处理 本作品最后修改时间:2026-05-22 23:44:50