# Java 序列化与 Jackson 序列化机制对比

1. Java 序列化机制

1.1 定义

Java 序列化是将对象的状态转换为字节序列的过程,以便可以将对象持久化到文件、通过网络传输或存储到缓存中。反序列化则是将字节序列恢复为对象的过程。

1.2 实现 Serializable 接口

  • Serializable 接口:是一个标记接口,没有方法。它用于指示 Java 序列化机制该类的对象可以被序列化。

  • 示例

    java 复制代码
    import java.io.Serializable;
    
    public class MyObject implements Serializable {
        private static final long serialVersionUID = 1L;
    
        private String name;
        private int age;
    
        // Getters and Setters
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        @Override
        public String toString() {
            return "MyObject{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }

1.3 序列化与反序列化操作

  • 序列化 :使用 ObjectOutputStream 将对象写入流。

    java 复制代码
    import java.io.FileOutputStream;
    import java.io.ObjectOutputStream;
    
    public class SerializationExample {
        public static void main(String[] args) {
            MyObject myObject = new MyObject();
            myObject.setName("Kimi");
            myObject.setAge(25);
    
            try (FileOutputStream fileOutputStream = new FileOutputStream("myObject.ser");
                 ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream)) {
                objectOutputStream.writeObject(myObject);
                System.out.println("Object serialized successfully.");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
  • 反序列化 :使用 ObjectInputStream 从流中读取对象。

    java 复制代码
    import java.io.FileInputStream;
    import java.io.ObjectInputStream;
    
    public class DeserializationExample {
        public static void main(String[] args) {
            try (FileInputStream fileInputStream = new FileInputStream("myObject.ser");
                 ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream)) {
                MyObject myObject = (MyObject) objectInputStream.readObject();
                System.out.println("Deserialized Object: " + myObject.toString());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

1.4 serialVersionUID 的作用

  • 唯一标识符serialVersionUID 是一个静态常量字段,用于标识类的版本。它在序列化和反序列化过程中用于验证类的版本是否一致。

  • 自动生成 :如果不显式定义 serialVersionUID,Java 会根据类的结构自动生成一个值。但建议显式定义一个固定的值,以避免因类结构变化导致的版本不一致问题。

  • 示例

    java 复制代码
    private static final long serialVersionUID = 1L;

1.5 类结构变化与 serialVersionUID

  • 字段添加/删除

    • 如果类的结构变化不大(如添加或删除一些非关键字段),可以保持 serialVersionUID 不变。反序列化时,新字段的值会是其默认值。

    • 示例:添加字段 address,但保持 serialVersionUID 不变。

      java 复制代码
      private String address;
  • 字段类型改变

    • 如果字段类型发生改变,需要更新 serialVersionUID 的值。否则,反序列化时会抛出 InvalidClassException

    • 示例:将字段 ageint 改为 String,并更新 serialVersionUID

      java 复制代码
      private static final long serialVersionUID = 2L;
      private String age;
  • 字段数量大幅变化

    • 如果字段数量发生大幅变化(如删除多个字段),建议更新 serialVersionUID 的值,以避免反序列化时出现不一致的问题。

1.6 注意事项

  • 安全性:反序列化时可能会引入安全风险,建议仅从可信源加载序列化数据。
  • 性能:Java 的默认序列化机制相对低效,如果需要高性能,可以考虑使用更高效的序列化框架(如 Kryo、Protocol Buffers 等)。

2. Jackson 序列化机制

2.1 定义

Jackson 是一个流行的 JSON 处理库,用于将 Java 对象序列化为 JSON 格式的字符串,以及将 JSON 格式的字符串反序列化为 Java 对象。它广泛应用于 RESTful API 的开发中。

2.2 使用 Jackson 进行序列化和反序列化

  • 序列化:将 Java 对象转换为 JSON 格式的字符串。

    java 复制代码
    import com.fasterxml.jackson.databind.ObjectMapper;
    
    public class JacksonSerializationExample {
        public static void main(String[] args) {
            MyObject myObject = new MyObject();
            myObject.setName("Kimi");
            myObject.setAge(25);
    
            try {
                ObjectMapper objectMapper = new ObjectMapper();
                String jsonString = objectMapper.writeValueAsString(myObject);
                System.out.println("Serialized JSON: " + jsonString);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
  • 反序列化:将 JSON 格式的字符串转换为 Java 对象。

    java 复制代码
    import com.fasterxml.jackson.databind.ObjectMapper;
    
    public class JacksonDeserializationExample {
        public static void main(String[] args) {
            String jsonString = "{\"name\":\"Kimi\",\"age\":25}";
    
            try {
                ObjectMapper objectMapper = new ObjectMapper();
                MyObject myObject = objectMapper.readValue(jsonString, MyObject.class);
                System.out.println("Deserialized Object: " + myObject.toString());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

2.3 Jackson 的特点

  • 基于 JSON:Jackson 使用 JSON 格式进行序列化和反序列化,适合 Web 应用和 RESTful API。
  • 注解支持 :通过注解(如 @JsonProperty@JsonIgnore 等)可以控制序列化和反序列化的行为。
  • 性能优化:Jackson 提供了高效的序列化和反序列化性能,适合处理大量数据。

2.4 示例类

java 复制代码
import com.fasterxml.jackson.annotation.JsonProperty;

public class MyObject {
    @JsonProperty("name")
    private String name;

    @JsonProperty("age")
    private int age;

    // Getters and Setters
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "MyObject{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

3. Jackson 与 Java 序列化机制的不同

3.1 序列化格式

  • Java 序列化:将对象序列化为二进制格式,适合持久化和网络传输。
  • Jackson 序列化:将对象序列化为 JSON 格式的字符串,适合 Web 应用和 RESTful API。

3.2 是否需要实现接口

  • Java 序列化 :需要实现 java.io.Serializable 接口。
  • Jackson 序列化:不需要实现任何接口,但可以通过注解来控制序列化和反序列化的行为。

3.3 性能

  • Java 序列化:相对低效,尤其是处理大量数据时。
  • Jackson 序列化:性能优化较好,适合处理大量数据。

3.4 安全性

  • Java 序列化:存在反序列化漏洞的风险,建议仅从可信源加载序列化数据。
  • Jackson 序列化:相对安全,但仍需注意 JSON 数据的来源。

3.5 使用场景

  • Java 序列化:适合需要将对象持久化为二进制文件或通过网络传输二进制数据的场景。
  • Jackson 序列化:适合需要将对象转换为 JSON 格式(如 RESTful API 的响应)或从 JSON 格式还原为对象的场景。

4. 总结

  • Java 序列化

    • 需要实现 Serializable 接口。
    • 使用二进制格式,适合持久化和网络传输。
    • 需要显式定义 serialVersionUID,并在类结构发生变化时手动更新。
    • 相对低效,存在安全风险。
  • Jackson 序列化

    • 不需要实现任何接口
相关推荐
SoniaChen3320 分钟前
Rust基础-part3-函数
开发语言·后端·rust
全干engineer26 分钟前
Flask 入门教程:用 Python 快速搭建你的第一个 Web 应用
后端·python·flask·web
William一直在路上1 小时前
SpringBoot 拦截器和过滤器的区别
hive·spring boot·后端
小马爱打代码2 小时前
Spring Boot 3.4 :@Fallback 注解 - 让微服务容错更简单
spring boot·后端·微服务
曾曜2 小时前
PostgreSQL逻辑复制的原理和实践
后端
豌豆花下猫2 小时前
Python 潮流周刊#110:JIT 编译器两年回顾,AI 智能体工具大爆发(摘要)
后端·python·ai
轻语呢喃2 小时前
JavaScript :事件循环机制的深度解析
javascript·后端
ezl1fe2 小时前
RAG 每日一技(四):让AI读懂你的话,初探RAG的“灵魂”——Embedding
后端
经典19922 小时前
spring boot 详解以及原理
java·spring boot·后端
Aurora_NeAr2 小时前
Apache Iceberg数据湖高级特性及性能调优
大数据·后端