如何處理 Avro 中的預設值
一、簡介
在本教程中,我們將探索 Apache Avro 資料序列化/反序列化框架。此外,我們將學習如何使用初始化和序列化物件時使用的預設值來處理模式定義。
2.Avro是什麼?
Apache Avro 是傳統資料格式化方法的更強大替代方案。通常,它使用 JSON 進行架構定義。此外,Avro 最受歡迎的用例涉及 Apache Kafka、Hive 或 Impala。 Avro 在即時處理大量資料(寫入密集型、大數據操作)方面非常有用。
讓我們將 Avro 視為由架構定義,並且該架構是用 JSON 編寫的。
Avro 的優點是:
- 資料自動壓縮(需要更少的CPU資源)
- 資料是完全類型化的(稍後我們將看到如何聲明每個屬性的類型)
- 模式伴隨數據
- 文件嵌入到架構中
- 感謝 JSON,可以用任何語言讀取數據
- 安全模式演化
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>
現在讓我們定義一個範例模式,Avro 使用它來產生範例類別。此架構是 JSON 格式的物件定義,儲存在文字檔案中。我們必須確保該檔案具有.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"
}
]
}
讓我們更詳細地看一下該架構。 namespace
是將產生的record
類別新增到的位置。 record
是一種特殊類型的 Java 類,它可以幫助我們使用比普通類別更少的樣板程式碼來建模純資料聚合。總的來說,Avro 支援六種複雜類型: record
、 enum
、 array
、 map
、 union
和fixed
。
在我們的範例中, type
是一筆record
。 name
是類別的名稱, fields
是類別的屬性及其類型。這是我們處理預設值的地方。
4.Avro預設值
Avro 的一個重要方面是可以透過使用union
使字段成為可選字段,在這種情況下它預設為null
,或者可以在未初始化時為其分配特定的預設值。因此,我們要么有一個預設為null
可選字段,要么使用我們在架構中指定的預設值初始化該字段。
現在,讓我們來看看配置預設值的新架構:
{
"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
}
]
}
我們看到有兩種類型的屬性: String
和int.
我們還注意到屬性除了type, default.
這允許類型不被初始化並且預設為指定的值。
為了在初始化物件時使用預設值,我們必須使用 Avro 生成類別的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());
}
我們實例化了一個新的car
對象,並且只設定了color
屬性,這也是唯一必需的屬性。檢查屬性,我們看到brand
被初始化為Dacia,
number_of_doors
被初始化為4
(兩者都被分配了架構中的預設值)並且color
預設為null
。
此外,在欄位中新增可選語法 ( union
) 會強制它採用該值。因此,即使欄位是int
,預設值也將為null.
當我們想要確保該欄位尚未設定時,這可能很有用:
{
"name": "number_of_wheels",
"type": ["null", "int"],
"default": null
}
5. 結論
Avro 的創建是為了滿足大數據處理背景下高效序列化的需求。
在本文中,我們了解了 Apache 的資料序列化/反序列化框架 Avro。此外,我們也介紹了它的優點和設定。然而,最重要的是,我們已經學習瞭如何配置模式以接受預設值。
與往常一樣,程式碼可以在 GitHub 上取得。