如何定义一个可选的类列表作为Avro模式中的字段之一,以避免Avro序列化错误?



我的需求是将数据存储在数据库中:如果addresses作为请求通过邮差发送,则currentAddresspreviousAddresses不应发送&如果两者都被发送,那么addresses根本不应该被发送。

Addresses、PreviousAddresses和CurrentAddress被定义为:

private List<MyClassOldAddress> addresses;
private List<MyClassAddress> previousAddresses;
private MyClassAddress currentAddress;

我做了什么:我已经定义了一个Avro-Schema(使用v1.11.1),如下所示,它被转换为Java类,由API使用,我们在其中发送请求体以将数据存储在数据库中。

{
"namespace":"com.avro.data",
"type":"record",
"name":"MyClass",
"fields":[
{
"name":"userId",
"type":"string",
"docs":"This is the unique id for user."
},
{
"name":"middleName",
"type":[
"null",
"string"
],
"avro.java.string":"String"
},
{
"name":"firstName",
"type":"string",
"avro.java.string":"String"
},
{
"name":"lastName",
"type":"string",
"avro.java.string":"String"
},
{
"name":"addresses",
"type":{
"type":"array",
"items":"com.data.MyClassAddress"
},
"default": []
},
{
"name":"previousAddresses",
"type":{
"type":"array",
"items":"com.data.MyClassOtherAddress"
},
"default": []
},
{
"name": "currentAddress",
"type": [
"null",
"com.data.MyClassOtherAddress"
],
"default": null
}
]
}

当我从Postman传递请求并发送字段addressescurrentAddresspreviousAddresses为null或空[]时,它会抛出一些错误:

请求1:

{
"userId":"123",
"middle_name":"user_middle_name",
"first_name":"user_first_name",
"last_name":"user_last_name",
"addresses":[
{
"street_name":"testing",
"town":"testing",
"country":"ABC",
"postcode":"123456",
"house_number":"123",
"start_date":"2000-01"
}
],
"previous_addresses":[],
"current_address":null
}

请求2:

{
"userId":"123",
"middle_name":"user_middle_name",
"first_name":"user_first_name",
"last_name":"user_last_name",
"addresses":[],
"previous_addresses":[...some data here...],
"current_address":{...some data here...}
}

错误:

Caused by: java.lang.NullPointerException: null value for (non-nullable) List<MyClassAddress> at
Caused by: org.apache.kafka.common.errors.SerializationException: Error serializing Avro message

我的观察:通过识别,我知道如果任何字段(addressescurrentAddresspreviousAddresses)作为null或[]发送,则在将其存储在数据库之前无法序列化。

但是当我在这些对象中放入任何东西时,它不会失败。但是我做不到,我必须按要求设置。

那么,我如何避免这种事情,使Avro-Schema中的所有3个字段作为可选字段,以便在序列化时不会产生任何问题?

我试着添加"default:[]", "default: null";但是没有一个成功!请帮助。

我尝试发送请求与一些条件(当地址发送时,currentAddress和preousaddresses不应该发送,反之亦然),但它在序列化失败。

我希望它工作没有序列化错误,如果字段丢失(按要求),它不应该失败。

不要错过avro模式avsc文件中使用的任何字段或类,即使它是可选的。在序列化时只使用空值序列化以满足模式形式,因为反序列化器将查找骨架,如果缺少任何内容,它将失败。

Avro要求严格的模式兼容性,这意味着用于序列化数据的模式必须与用于反序列化数据的模式完全相同。例如,当您的可选字段从请求体中丢失时(您试图通过Postman发送),反序列化器将无法将丢失的字段与模式中的字段进行匹配,从而导致Avro模式序列化错误。

我建议你使用IF条件保持null检查,并为可选字段/类的每个字段创建一个空/空构造函数,以避免在反序列化时在每个模式中丢失字段。通过这种方式,您不会在特定类的可选字段中传递任何值,另一方面,满足模式字段,以便反序列化器检查并满足根据定义的模式没有丢失任何内容。

最新更新