1. 简介

本文将深入探讨 Apache Avro 数据序列化/反序列化框架。重点学习如何在对象初始化和序列化时处理默认值的 schema 定义

2. Avro 是什么?

Apache Avro 是传统数据格式的强力替代方案。它通常使用 JSON 定义 schema,在 Apache Kafka、Hive 或 Impala 等场景中广泛使用。Avro 特别适合处理实时大数据(写密集型操作)。

简单理解:Avro 由 JSON 格式的 schema 定义驱动

核心优势: ✅ 数据自动压缩(节省 CPU 资源) ✅ 强类型系统(每个属性都需声明类型) ✅ 数据自带 schema ✅ 文档内嵌在 schema 中 ✅ 基于 JSON 实现跨语言支持 ✅ 安全的 schema 演进机制

3. Avro 环境搭建

首先添加 Avro Maven 依赖:

<dependencies> 
    <dependency> 
        <groupId>org.apache.avro</groupId> 
        <artifactId>avro</artifactId>
        <version>1.11.3</version>
    </dependency> 
</dependencies>

接着配置 avro-maven-plugin 辅助代码生成:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.avro</groupId>
            <artifactId>avro-maven-plugin</artifactId>
            <version>1.11.3</version>
            <configuration>
                <sourceDirectory>${project.basedir}/src/main/java/com/baeldung/avro/</sourceDirectory>
                <outputDirectory>${project.basedir}/src/main/java/com/baeldung/avro/</outputDirectory>
                <stringType>String</stringType>
            </configuration>
            <executions>
                <execution>
                    <phase>generate-sources</phase>
                    <goals>
                        <goal>schema</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

现在定义示例 schema(文件扩展名必须是 .avsc),这里命名为 car.avsc

{
    "namespace": "generated.avro",
     "type": "record",
     "name": "Car",
     "fields": [
         {  "name": "brand",
            "type": "string"
         },
         {  "name": "number_of_doors",
            "type": "int"
         },
         {  "name": "color",
            "type": "string"
         }
     ]
}

Schema 关键要素解析:

  • namespace:生成类的包路径
  • record:特殊 Java 类型,比普通类更简洁(Avro 支持 6 种复杂类型:recordenumarraymapunionfixed
  • fields重点!默认值就在这里配置

4. Avro 默认值处理

**核心要点:字段可通过 union 设为可选(默认 null),或指定具体默认值**。两种模式:

  1. 可选字段 → 默认 null
  2. 必填字段 → 使用 schema 定义的默认值

升级后的 schema 示例:

{
    "namespace": "generated.avro",
    "type": "record",
    "name": "Car",
    "fields": [
        {   "name": "brand",
            "type": "string",
            "default": "Dacia"
         },
        {   "name": "number_of_doors",
            "type": "int",
            "default": 4
        },
        {   "name": "color",
            "type": ["null", "string"],
            "default": null
        }
    ]
}

⚠️ 踩坑提醒:要使默认值生效,必须使用生成类的 newBuilder() 方法!测试用例演示:

@Test
public void givenCarJsonSchema_whenCarIsSerialized_thenCarIsSuccessfullyDeserialized() throws IOException {

    Car car = Car.newBuilder()
      .build();

    SerializationDeserializationLogic.serializeCar(car);
    Car deserializedCar = SerializationDeserializationLogic.deserializeCar();

    assertEquals("Dacia", deserializedCar.getBrand());
    assertEquals(4, deserializedCar.getNumberOfDoors());
    assertNull(deserializedCar.getColor());
}

验证结果:

  • brand 默认为 "Dacia"
  • number_of_doors 默认为 4
  • color 因设为可选字段(union 类型)默认为 null

进阶技巧:强制字段为可选(即使原始类型是 int):

{ 
    "name": "number_of_wheels", 
    "type": ["null", "int"], 
    "default": null 
}

5. 总结

Avro 专为大数据场景的高效序列化而生。

本文系统介绍了: ✅ Avro 核心优势与搭建流程 ✅ 重点:Schema 默认值配置方案 ✅ 实际应用中的注意事项

完整代码示例见 GitHub 仓库


原始标题:How to Handle Default Values in Avro | Baeldung