使用对象列表创建 Avro Schema

在本文中,我们研究了如何创建包含对象列表的 Avro 模式shcema。此外,我们还详细介绍了如何 使用 子 记录的列表 属性 定义父记录 。这是我们在 Avro 中表示复杂数据结构的一种方式。此外,当我们需要处理对象集合或分层数据时,这特别有用。
最后,Avro 模式非常灵活,我们可以配置它们来设置更复杂的数据结构。我们可以组合不同的类型和嵌套结构来复制我们的数据模型。

Apache Avro是一个数据序列化框架,它提供强大的数据结构和轻量级、快速的二进制数据格式。

在本教程中,我们将探讨如何创建一个 Avro 模式,当转换为对象时,该模式包含其他对象的列表。

目标
假设我们要开发一个表示父子关系的 Avro 模式。因此,我们需要一个 包含Child 对象列表的 Parent类。

Java 代码如下所示:

public class Child {
    String name;
}
public class Parent {
    List<Child> children;
}

我们的目标是创建一个 Avro 模式shcema,将其结构转换为这些对象。

在我们研究解决方案之前,让我们快速了解一些 Avro 基础知识:

  • Avro 模式使用JSON定义
  • 类型 字段指的是数据类型(例如,记录,数组,字符串)
  • 字段数组 定义记录的结构

创建 Avro 模式
为了正确说明 Avro 中的父子关系,我们需要使用记录 和 数组 类型的组合。

该架构如下所示:

{
    "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 。

在 Java 中使用 Schema
一旦定义了 Avro 模式,我们就会使用它来生成 Java 类。当然,我们将使用 Avro Maven 插件来执行此操作。以下是 父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 工具窗口的插件部分并运行avro插件的avro:schema目标

这样,Avro 就会根据提供的模式在提供的命名空间中创建 Java 类。 命名空间属性还会在生成的类的顶部添加包名称。

使用生成的类
新创建的类提供了设置方法,用于获取和设置子列表。如下所示:

@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 属性中。最后,我们对对象进行序列化和反序列化,并比较其中一个名称。