序列化(Serialization)是将对象转换为可存储或传输的格式的过程。对于 Java 中的 JSON 序列化,通常是将 Java 对象转换成 JSON 字符串,以便传输到网络中或保存到文件中。反序列化则是将 JSON 字符串转换回 Java 对象的过程。
序列化 是指将对象的状态转换为一种 可存储 或 可传输 的格式的过程。这种格式通常是字节流(如 JSON、XML 或二进制格式),可以存储在文件、数据库中,或者通过网络进行传输。在接收端,可以通过 反序列化(Deserialization) 将字节流重新还原为对象。
在 Jackson 中,序列化的核心任务是将 Java 对象转换为 JSON 格式。ObjectMapper
类在 Jackson 库中提供了非常方便的 API 来实现这一过程。
import com.fasterxml.jackson.databind.ObjectMapper;
public class SerializationExample {
public static void main(String[] args) throws Exception {
// 创建一个 Person 对象
Person person = new Person("John", 30);
// 创建 ObjectMapper 实例
ObjectMapper objectMapper = new ObjectMapper();
// 序列化:Java 对象转 JSON 字符串
String jsonString = objectMapper.writeValueAsString(person);
System.out.println(jsonString);
}
}
结果
{"name":"John","age":30}
序列化的详细过程
在 Jackson 中,序列化的过程包含以下步骤:
- 获取 Java 对象的类信息:Jackson 会根据 Java 对象的类型,获取类的字段(属性)。
- 转换 Java 对象的字段:它会遍历 Java 对象的属性,找到公共字段或通过 getter 方法访问属性,将其转化为相应的 JSON 键值对。
- 生成 JSON 数据:这些键值对会被合并成一个 JSON 对象,转换过程最终生成 JSON 格式的字符串。
序列化底层实现概览
序列化的核心是 ObjectMapper
和它使用的一些辅助类,如 JsonGenerator
、SerializerProvider
、JsonSerializer
等。具体的底层实现逻辑可以分为几个主要步骤:
- 找到正确的序列化器 (
JsonSerializer
) - 通过
JsonGenerator
写出 JSON 数据 - 处理属性、类型等定制逻辑
序列化方法
ObjectMapper.writeValue()
ObjectMapper
是 Jackson 序列化和反序列化的核心工具,它提供了多种方法来实现序列化。例如,writeValueAsString()
将 Java 对象转换为 JSON 字符串,writeValue()
将 Java 对象写入到输出流中。
2. 序列化流程解析
2.1. 处理 null
值
首先,在序列化过程中,ObjectMapper
会判断对象是否为 null
。如果是 null
,它会调用 _serializeNull()
方法,这通常会生成 JSON 中的 "null"
字符串。
2.2. 获取序列化器
如果对象不为 null
,ObjectMapper
会根据对象的类型(即 value.getClass()
)从 SerializerProvider
中查找合适的序列化器(JsonSerializer
)。SerializerProvider
会缓存已经创建过的序列化器,并根据需要提供给 ObjectMapper
。
public JsonSerializer<Object> findValueSerializer(Class<?> valueType, SerializationConfig config) {
// 从缓存中查找序列化器,如果没有则创建新的序列化器
JsonSerializer<Object> serializer = _serializerCache.get(valueType);
if (serializer == null) {
// 通过类型创建一个新的序列化器
serializer = _createSerializer(config, valueType);
_serializerCache.put(valueType, serializer);
}
return serializer;
}
2.3. 调用序列化器的 serialize()
方法
一旦获得了合适的序列化器,ObjectMapper
就会调用序列化器的 serialize()
方法来将 Java 对象转换为 JSON 数据。
public void serialize(Object value, JsonGenerator gen, SerializerProvider provider) throws IOException {
// 实际的序列化过程
gen.writeStartObject(); // 开始一个 JSON 对象
// 通过遍历 Java 对象的字段并序列化每个字段
gen.writeEndObject(); // 结束一个 JSON 对象
}
在序列化过程中,Jackson 会遍历 Java 对象的字段或 getter 方法,并将其转化为 JSON 中的键值对。例如,Person
类中的 name
和 age
字段会被转换为 JSON 对象中的 "name": "John", "age": 30
。
Jackson 通过反射机制或者使用 JavaBean 属性访问器(getter/setter)来获取 Java 对象的属性。这部分代码会遍历对象的属性,并调用相应的 writeXXX
方法将每个属性序列化为 JSON。
完整序列化示例
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;
public class JacksonSerializationExample {
public static void main(String[] args) throws Exception {
// 创建一个 Java 对象
Person person = new Person("John", 30);
// 创建 ObjectMapper 实例
ObjectMapper objectMapper = new ObjectMapper();
// 序列化:Java 对象转 JSON 字符串
String jsonString = objectMapper.writeValueAsString(person);
System.out.println(jsonString);
}
}
class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
class PersonSerializer extends JsonSerializer<Person> {
@Override
public void serialize(Person person, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeStartObject(); // 开始序列化对象
gen.writeStringField("name", person.getName()); // 写入 name 字段
gen.writeNumberField("age", person.getAge()); // 写入 age 字段
gen.writeEndObject(); // 结束序列化对象
}
}
findValueSerializer()
方法
findValueSerializer()
是 SerializerProvider
中的一个重要方法,它的作用是返回一个适用于指定类型的序列化器。具体来说,方法的定义如下:
public JsonSerializer<Object> findValueSerializer(Class<?> valueType, SerializationConfig config) {
// 通过类型查找或创建序列化器
JsonSerializer<Object> serializer = _serializerCache.get(valueType);
if (serializer == null) {
// 如果缓存中没有找到该类型的序列化器,则创建一个新的序列化器
serializer = _createSerializer(config, valueType);
_serializerCache.put(valueType, serializer); // 缓存序列化器
}
return serializer;
}
findValueSerializer
的主要工作流程:
-
缓存查找:首先,
findValueSerializer()
会查看_serializerCache
中是否已经存在针对给定类型(valueType
)的序列化器。如果找到了,它直接返回该序列化器。 -
序列化器创建:如果缓存中没有该类型的序列化器,
findValueSerializer()
会通过_createSerializer()
方法创建一个新的序列化器。该方法根据对象类型、配置和其他因素(如@JsonSerialize
注解等)来选择和创建适当的序列化器。 -
缓存:新的序列化器创建后,会被缓存到
_serializerCache
中,以提高性能,避免重复创建相同类型的序列化器。
缓存机制
Jackson 会缓存已经创建过的序列化器,以避免每次序列化时都需要重复创建新的序列化器。通过 _serializerCache.get(valueType)
,Jackson 会先从缓存中检查是否已有该类型的序列化器。如果没有,才会调用 _createSerializer()
创建一个新的序列化器。这大大提高了性能,尤其是在大量序列化相同类型对象时。
1. 手动实现 JSON 序列化
以下代码实现了将对象手动序列化为 JSON 格式,并从 JSON 字符串反序列化为对象。
import java.util.HashMap;
import java.util.Map;
class Person {
private String name;
private int age;
public Person() {} // 无参构造函数
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// 序列化为 JSON 字符串
public String toJson() {
return "{" +
"\"name\":\"" + name + "\"," +
"\"age\":" + age +
"}";
}
// 从 JSON 字符串反序列化为对象
public static Person fromJson(String json) {
Map<String, String> map = parseJson(json);
return new Person(map.get("name"), Integer.parseInt(map.get("age")));
}
// 简单解析 JSON(不支持复杂 JSON,仅用于示例)
private static Map<String, String> parseJson(String json) {
Map<String, String> map = new HashMap<>();
json = json.replace("{", "").replace("}", "").replace("\"", "");
String[] entries = json.split(",");
for (String entry : entries) {
String[] keyValue = entry.split(":");
map.put(keyValue[0].trim(), keyValue[1].trim());
}
return map;
}
@Override
public String toString() {
return "Person{name='" + name + "', age=" + age + '}';
}
}
public class CustomJsonSerialization {
public static void main(String[] args) {
// 创建对象
Person person = new Person("Alice", 25);
// 序列化为 JSON
String json = person.toJson();
System.out.println("Serialized JSON: " + json);
// 从 JSON 反序列化为对象
Person deserializedPerson = Person.fromJson(json);
System.out.println("Deserialized Object: " + deserializedPerson);
}
}
2. 手动实现 XML 序列化
实现对象到 XML 格式的序列化和反序列化。
class Person {
private String name;
private int age;
public Person() {} // 无参构造函数
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// 序列化为 XML 字符串
public String toXml() {
return "<Person>" +
"<name>" + name + "</name>" +
"<age>" + age + "</age>" +
"</Person>";
}
// 从 XML 字符串反序列化为对象
public static Person fromXml(String xml) {
String name = xml.substring(xml.indexOf("<name>") + 6, xml.indexOf("</name>"));
int age = Integer.parseInt(xml.substring(xml.indexOf("<age>") + 5, xml.indexOf("</age>")));
return new Person(name, age);
}
@Override
public String toString() {
return "Person{name='" + name + "', age=" + age + '}';
}
}
public class CustomXmlSerialization {
public static void main(String[] args) {
// 创建对象
Person person = new Person("Bob", 30);
// 序列化为 XML
String xml = person.toXml();
System.out.println("Serialized XML: " + xml);
// 从 XML 反序列化为对象
Person deserializedPerson = Person.fromXml(xml);
System.out.println("Deserialized Object: " + deserializedPerson);
}
}
3. 手动实现二进制序列化
二进制序列化是将对象的数据写入字节流。以下是手动将对象序列化为字节数组并反序列化的实现:
class Person {
private String name;
private int age;
public Person() {} // 无参构造函数
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// 序列化为 XML 字符串
public String toXml() {
return "<Person>" +
"<name>" + name + "</name>" +
"<age>" + age + "</age>" +
"</Person>";
}
// 从 XML 字符串反序列化为对象
public static Person fromXml(String xml) {
String name = xml.substring(xml.indexOf("<name>") + 6, xml.indexOf("</name>"));
int age = Integer.parseInt(xml.substring(xml.indexOf("<age>") + 5, xml.indexOf("</age>")));
return new Person(name, age);
}
@Override
public String toString() {
return "Person{name='" + name + "', age=" + age + '}';
}
}
public class CustomXmlSerialization {
public static void main(String[] args) {
// 创建对象
Person person = new Person("Bob", 30);
// 序列化为 XML
String xml = person.toXml();
System.out.println("Serialized XML: " + xml);
// 从 XML 反序列化为对象
Person deserializedPerson = Person.fromXml(xml);
System.out.println("Deserialized Object: " + deserializedPerson);
}
}