1. 概述
Apache Avro 是一个数据序列化框架,提供强大的数据结构和轻量级、快速的二进制数据格式。
在本教程中,我们将探索如何创建一个 Avro schema,当它转换为对象时,包含其他对象的列表。
2. 目标
假设我们需要开发一个表示父子关系的 Avro schema。因此,我们需要一个包含多个 Child 对象列表的 Parent 类。
在 Java 代码中可能长这样:
public class Child {
String name;
}
public class Parent {
List<Child> children;
}
我们的目标是创建一个能自动转换为这些对象的 Avro schema。
在看解决方案前,快速回顾几个 Avro 基础概念:
- Avro schema 使用 JSON 定义
- type 字段表示数据类型(如 record, array, string)
- fields 数组定义记录的结构
3. 创建 Avro Schema
要在 Avro 中正确表示父子关系,我们需要组合使用 record 和 array 类型。
schema 如下所示:
{
"namespace": "com.baeldung.apache.avro.generated",
"type": "record",
"name": "Parent",
"fields": [
{
"name": "children",
"type": {
"type": "array",
"items": {
"type": "record",
"name": "Child",
"fields": [
{"name": "name", "type": "string"}
]
}
}
}
]
}
我们首先定义了一个 Parent 类型的记录。在 Parent 记录中,我们定义了一个 children 字段。这个字段是 数组 类型,允许我们存储多个 Child 对象。数组类型的 items 属性详细描述了数组中每个元素的结构。在我们的例子中,这是一个 Child 记录。可以看到,Child 记录只有一个属性 name,类型为 string。
4. 在 Java 中使用 Schema
定义好 Avro schema 后,我们将用它生成 Java 类。当然,这需要通过 Avro Maven 插件完成。以下是 parent pom 文件中的配置:
<plugin>
<groupId>org.apache.avro</groupId>
<artifactId>avro-maven-plugin</artifactId>
<version>1.11.3</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>schema</goal>
</goals>
<configuration>
<sourceDirectory>src/main/java/com/baeldung/apache/avro/schemas</sourceDirectory>
<outputDirectory>src/main/java</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
要让 Avro 生成类,我们需要运行 Maven 生成源码命令(mvn clean generate-sources
),或者到 Maven 工具窗口的 Plugins 部分运行 avro 插件的 avro:schema 目标:
这样,Avro 会根据提供的 schema 在指定的 namespace 中创建 Java 类。namespace 属性还会在生成类的顶部添加包名。
5. 使用生成的类
新生成的类提供了设置和获取 children 列表的方法。具体如下:
@Test
public void whenAvroSchemaWithListOfObjectsIsUsed_thenObjectsAreSuccessfullyCreatedAndSerialized() throws IOException {
Parent parent = new Parent();
List<Child> children = new ArrayList();
Child child1 = new Child();
child1.setName("Alice");
children.add(child1);
Child child2 = new Child();
child2.setName("Bob");
children.add(child2);
parent.setChildren(children);
SerializationDeserializationLogic.serializeParent(parent);
Parent deserializedParent = SerializationDeserializationLogic.deserializeParent();
assertEquals("Alice", deserializedParent.getChildren().get(0).getName());
}
从上面的测试可以看到,我们创建了一个新的 Parent 对象。也可以使用提供的 builder() 方法创建(这篇关于 Avro 默认值 的文章展示了如何使用 builder() 模式)。
然后,我们创建了两个 Child 对象并添加到 Parent 的 children 属性中。最后,我们序列化和反序列化对象,并比较其中一个名字。
6. 总结
本文介绍了如何创建包含对象列表的 Avro schema。我们详细说明了如何定义一个带有 Child 记录列表属性的 Parent 记录。这是在 Avro 中表示复杂数据结构的一种方式。当我们需要处理对象集合或分层数据时,这种方法特别有用。
最后,Avro schema 非常灵活,我们可以配置它们来设置更复杂的数据结构。通过组合不同类型和嵌套结构,可以复制我们的数据模型。