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

    • 不需要实现任何接口
相关推荐
野犬寒鸦17 分钟前
从零起步学习并发编程 || 第一章:初步认识进程与线程
java·服务器·后端·学习
我爱娃哈哈22 分钟前
SpringBoot + Flowable + 自定义节点:可视化工作流引擎,支持请假、报销、审批全场景
java·spring boot·后端
李梨同学丶2 小时前
0201好虫子周刊
后端
思想在飞肢体在追2 小时前
Springboot项目配置Nacos
java·spring boot·后端·nacos
Loo国昌5 小时前
【垂类模型数据工程】第四阶段:高性能 Embedding 实战:从双编码器架构到 InfoNCE 损失函数详解
人工智能·后端·深度学习·自然语言处理·架构·transformer·embedding
ONE_PUNCH_Ge6 小时前
Go 语言泛型
开发语言·后端·golang
良许Linux6 小时前
DSP的选型和应用
后端·stm32·单片机·程序员·嵌入式
不光头强6 小时前
spring boot项目欢迎页设置方式
java·spring boot·后端
怪兽毕设6 小时前
基于SpringBoot的选课调查系统
java·vue.js·spring boot·后端·node.js·选课调查系统
学IT的周星星7 小时前
Spring Boot Web 开发实战:第二天,从零搭个“会卖萌”的小项目
spring boot·后端·tomcat