# 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 序列化

    • 不需要实现任何接口
相关推荐
Moonbit4 分钟前
MoonBit Pearls Vol.05: 函数式里的依赖注入:Reader Monad
后端·rust·编程语言
bobz96530 分钟前
ThanosRuler
后端
用户48221371677535 分钟前
C++——字符串常量、二维数组、函数与指针的深度应用(补)
后端
用户48221371677537 分钟前
C++——类型转换
后端
lichenyang4531 小时前
mongoose(对象文档模型库)的使用
后端
用户4822137167751 小时前
C++——继承进阶
后端
洛卡卡了1 小时前
数据库加密方案实践:我们选的不是最完美,但是真的够用了。
数据库·后端·面试
Java中文社群1 小时前
淘宝首位程序员离职,竟投身AI新公司做这事!
人工智能·后端·程序员
big_eleven1 小时前
轻松掌握数据结构:二叉树
后端·算法·面试
big_eleven1 小时前
轻松掌握数据结构:二叉查找树
后端·算法·面试