在本文中,我们研究了如何创建包含对象列表的 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 属性中。最后,我们对对象进行序列化和反序列化,并比较其中一个名称。