Java 常见序列化协议

Java 提供了多种序列化协议来满足不同的需求。常见的序列化协议包括 Java 原生序列化协议JSON 序列化XML 序列化Protocol BuffersAvro 等。不同的序列化协议适用于不同的应用场景,选择合适的协议可以提高性能、兼容性和扩展性。

1. Java 原生序列化协议

1.1 概述

Java 原生序列化协议是通过 Java 提供的 Serializable 接口和 ObjectOutputStream / ObjectInputStream 实现的。它将对象转换为字节流,并能够恢复对象状态。其主要优点是简单、易用,但是存在一些性能和版本兼容性问题。

1.2 实现

Java 的原生序列化使用 ObjectOutputStreamObjectInputStream 来分别完成序列化和反序列化。

import java.io.*;

public class JavaSerializationExample {
    public static void main(String[] args) {
        Person person = new Person("John", 30);

        try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("person.ser"))) {
            out.writeObject(person);  // 序列化对象
        } catch (IOException e) {
            e.printStackTrace();
        }

        try (ObjectInputStream in = new ObjectInputStream(new FileInputStream("person.ser"))) {
            Person deserializedPerson = (Person) in.readObject();  // 反序列化对象
            System.out.println("Deserialized Name: " + deserializedPerson.getName());
            System.out.println("Deserialized Age: " + deserializedPerson.getAge());
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

class Person implements Serializable {
    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;
    }
}

1.3 优缺点

优点缺点
简单易用,原生支持 Java 对象序列化 性能差,序列化后的数据体积较大
可以序列化任何实现 Serializable 接口的对象 不支持跨语言使用,只有 Java 环境可以解析
可以保留对象的版本信息 (serialVersionUID) 不兼容对象结构的变化,类字段变动会导致反序列化失败
支持反序列化恢复完整对象的状态,包括字段、方法、继承结构等 无法有效压缩数据,对存储和传输数据的空间效率较低

2. JSON 序列化协议

2.1 概述

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,常用于 Web 应用和跨平台系统中。JSON 序列化将 Java 对象转换为 JSON 格式的字符串,反序列化则将 JSON 字符串转换回 Java 对象。常见的 JSON 序列化库有 Jackson、Gson 等。

2.2 实现

使用 Jackson 库来实现 JSON 序列化和反序列化。

添加 Jackson 依赖(Maven)

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.12.3</version>
</dependency>

代码示例:

import com.fasterxml.jackson.databind.ObjectMapper;

public class JsonSerializationExample {
    public static void main(String[] args) {
        Person person = new Person("John", 30);
        ObjectMapper objectMapper = new ObjectMapper();

        try {
            // 序列化为 JSON 字符串
            String json = objectMapper.writeValueAsString(person);
            System.out.println("Serialized JSON: " + json);

            // 反序列化为 Java 对象
            Person deserializedPerson = objectMapper.readValue(json, Person.class);
            System.out.println("Deserialized Name: " + deserializedPerson.getName());
            System.out.println("Deserialized Age: " + deserializedPerson.getAge());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

2.3 优缺点

优点缺点
人类可读,易于调试和查看数据 相较于二进制序列化,JSON 数据体积较大
序列化结果适合跨语言使用,几乎所有语言都支持 JSON 格式 对于大型对象,JSON 可能会变得不够高效
可通过框架如 Jackson、Gson 等实现自动映射 不支持对象的深层次复杂结构和自定义类型映射

3. XML 序列化协议

3.1 概述

XML(eXtensible Markup Language)是一种标记语言,用于表示结构化数据,广泛用于 Web 服务、配置文件和数据交换中。Java 提供了 JAXB(Java Architecture for XML Binding)来将 Java 对象序列化为 XML 数据,或将 XML 数据反序列化为 Java 对象。

3.2 实现

添加 JAXB 依赖(Maven)

<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>2.3.1</version>
</dependency>

代码示例:

import javax.xml.bind.*;

public class XmlSerializationExample {
    public static void main(String[] args) throws JAXBException {
        Person person = new Person("John", 30);
        JAXBContext context = JAXBContext.newInstance(Person.class);

        // 序列化 Java 对象为 XML
        Marshaller marshaller = context.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);  // 美化输出
        marshaller.marshal(person, System.out);  // 输出 XML

        // 反序列化 XML 为 Java 对象
        String xml = "<person><name>John</name><age>30</age></person>";
        Unmarshaller unmarshaller = context.createUnmarshaller();
        Person deserializedPerson = (Person) unmarshaller.unmarshal(new StringReader(xml));
        System.out.println("Deserialized Name: " + deserializedPerson.getName());
        System.out.println("Deserialized Age: " + deserializedPerson.getAge());
    }
}

3.3 优缺点

优点缺点
易于理解,广泛支持和兼容,适用于跨平台和跨语言应用 数据量较大,XML 格式的效率低于二进制格式
支持复杂数据结构,适合配置文件和复杂数据交换 序列化和反序列化过程较慢,性能差
强大的验证能力(可以使用 XSD 验证 XML 格式) 序列化后的数据冗长,不如 JSON 或二进制序列化紧凑

4. Protocol Buffers(Protobuf)

4.1 概述

Protocol Buffers(Protobuf)是 Google 提供的一种高效的、语言无关、平台无关的序列化协议。它通过定义 .proto 文件来描述数据结构,并生成对应的代码进行序列化和反序列化。Protobuf 格式比 XML 和 JSON 更紧凑、更高效,适用于高性能要求的系统。

4.2 实现

添加 Protobuf 依赖(Maven)

<dependency>
    <groupId>com.google.protobuf</groupId>
    <artifactId>protobuf-java</artifactId>
    <version>3.15.8</version>
</dependency>

代码示例:

import com.example.protobuf.PersonProto.Person;

public class ProtobufExample {
    public static void main(String[] args) throws Exception {
        // 序列化对象
        Person person = Person.newBuilder()
                .setName("John")
                .setAge(30)
                .build();
        byte[] data = person.toByteArray();
        
        // 反序列化对象
        Person deserializedPerson = Person.parseFrom(data);
        System.out.println("Deserialized Name: " + deserializedPerson.getName());
        System.out.println("Deserialized Age: " + deserializedPerson.getAge());
    }
}

4.3 优缺点

优点缺点
高效紧凑,数据体积小 需要定义 .proto 文件并生成代码,增加了额外的构建步骤
高性能,适用于需要高并发、高吞吐量的场景 对于复杂数据结构,理解和调试难度较大
支持跨语言,广泛用于分布式系统和微服务 不支持人类可读的格式(不像 JSON 或 XML)

5. Avro

5.1 概述

Avro 是 Apache 提供的一个高效序列化框架,适用于大数据处理,特别是在 Hadoop 生态系统中广泛应用。它提供了紧凑、快速的二进制序列化方式,并且支持动态模式和跨语言数据交换。

5.2 实现

添加 Avro 依赖(Maven)

<dependency>
    <groupId>org.apache.avro</groupId>
    <artifactId>avro</artifactId>
    <version>1.10.2</version>
</dependency>

代码示例:

import org.apache.avro.Schema;
import org.apache.avro.generic.GenericData;
import org.apache.avro.io.*;
import org.apache.avro.file.*;

import java.io.*;

public class AvroExample {
    public static void main(String[] args) throws IOException {
        // Define Avro schema
        String schemaString = "{\"type\":\"record\",\"name\":\"Person\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"age\",\"type\":\"int\"}]}";
        Schema schema = new Schema.Parser().parse(schemaString);

        // Create Avro data object
        GenericData.Record person = new GenericData.Record(schema);
        person.put("name", "John");
        person.put("age", 30);

        // Serialize to file
        File file = new File("person.avro");
        DatumWriter<GenericData.Record> writer = new GenericDatumWriter<>(schema);
        DataFileWriter<GenericData.Record> dataFileWriter = new DataFileWriter<>(writer);
        dataFileWriter.create(schema, file);
        dataFileWriter.append(person);
        dataFileWriter.close();

        // Deserialize from file
        DatumReader<GenericData.Record> reader = new GenericDatumReader<>(schema);
        DataFileReader<GenericData.Record> dataFileReader = new DataFileReader<>(file, reader);
        GenericData.Record deserializedPerson = dataFileReader.next();
        System.out.println("Deserialized Name: " + deserializedPerson.get("name"));
        System.out.println("Deserialized Age: " + deserializedPerson.get("age"));
    }
}

5.3 优缺点

优点缺点
高效、紧凑,适合大规模数据序列化 需要 Avro 模式文件,且与其他序列化协议不兼容
支持多种语言,并支持模式演化 较为复杂,开发时需要理解 Avro 模式的设计和使用
与 Hadoop 和 Spark 等大数据技术紧密集成 不是非常直观,较难调试和查看数据

总结

  • Java 原生序列化:简单但性能差,适用于 Java 内部应用。
  • JSON 序列化:适合跨语言、跨平台应用,但性能较差,数据体积较大。
  • XML 序列化:支持复杂数据结构,适合配置和数据交换,但数据量大且处理慢。
  • Protobuf:高效且跨语言,适合高性能要求的系统,广泛应用于分布式系统。
  • Avro:高效、紧凑,适合大数据处理,广泛应用于 Hadoop 和 Spark。
Java碎碎念 文章被收录于专栏

来一杯咖啡,聊聊Java的碎碎念呀

全部评论

相关推荐

求实习的小白1213:华科去这 你是真敢去啊
点赞 评论 收藏
分享
你背过凌晨4点的八股文么:简历挂了的话会是流程终止,像我一样
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务