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

eyh26e7m  于 2023-03-02  发布在  Spring
关注(0)|答案(2)|浏览(229)

**我的要求是将数据存储在数据库中:**如果addresses作为请求通过Postman发送,则不应发送currentAddresspreviousAddresses;如果两者都发送,则根本不应发送addresses
地址、先前地址和当前地址定义为:

  1. private List<MyClassOldAddress> addresses;
  2. private List<MyClassAddress> previousAddresses;
  3. private MyClassAddress currentAddress;

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

  1. {
  2. "namespace":"com.avro.data",
  3. "type":"record",
  4. "name":"MyClass",
  5. "fields":[
  6. {
  7. "name":"userId",
  8. "type":"string",
  9. "docs":"This is the unique id for user."
  10. },
  11. {
  12. "name":"middleName",
  13. "type":[
  14. "null",
  15. "string"
  16. ],
  17. "avro.java.string":"String"
  18. },
  19. {
  20. "name":"firstName",
  21. "type":"string",
  22. "avro.java.string":"String"
  23. },
  24. {
  25. "name":"lastName",
  26. "type":"string",
  27. "avro.java.string":"String"
  28. },
  29. {
  30. "name":"addresses",
  31. "type":{
  32. "type":"array",
  33. "items":"com.data.MyClassAddress"
  34. },
  35. "default": []
  36. },
  37. {
  38. "name":"previousAddresses",
  39. "type":{
  40. "type":"array",
  41. "items":"com.data.MyClassOtherAddress"
  42. },
  43. "default": []
  44. },
  45. {
  46. "name": "currentAddress",
  47. "type": [
  48. "null",
  49. "com.data.MyClassOtherAddress"
  50. ],
  51. "default": null
  52. }
  53. ]
  54. }

当我传递来自Postman的请求并按照如下要求将字段addressescurrentAddresspreviousAddresses作为null或empty []发送时,它抛出了一些错误:

请求1:

  1. {
  2. "userId":"123",
  3. "middle_name":"user_middle_name",
  4. "first_name":"user_first_name",
  5. "last_name":"user_last_name",
  6. "addresses":[
  7. {
  8. "street_name":"testing",
  9. "town":"testing",
  10. "country":"ABC",
  11. "postcode":"123456",
  12. "house_number":"123",
  13. "start_date":"2000-01"
  14. }
  15. ],
  16. "previous_addresses":[],
  17. "current_address":null
  18. }

请求2:

  1. {
  2. "userId":"123",
  3. "middle_name":"user_middle_name",
  4. "first_name":"user_first_name",
  5. "last_name":"user_last_name",
  6. "addresses":[],
  7. "previous_addresses":[...some data here...],
  8. "current_address":{...some data here...}
  9. }

错误:

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

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

但是当我把任何东西放进那些对象中时,它不会失败。但是我不能这样做,我必须按照要求设置。
那么,我如何避免这件事,使所有3个字段在Avro-Schema作为一个可选字段,使它不应该创建任何问题,而序列化?
我尝试添加“默认:[]",“默认:null”,“null”,但它们都不起作用!请帮助。
我尝试在某种条件下发送请求(发送地址时,不应发送currentAddress和previousAddresses,反之亦然),但在序列化时失败。
我希望它能在没有序列化错误的情况下工作,如果字段丢失(根据要求),它不应该失败。

aor9mmx1

aor9mmx11#

Avro要求严格的架构兼容性,这意味着用于序列化数据的架构必须与用于反序列化数据的架构完全相同。例如,当请求正文(您试图通过Postman发送)中缺少可选字段时,反序列化程序将无法将缺少的字段与架构中的字段匹配,从而导致Avro架构序列化错误。
我建议你用IF条件进行null检查,并为可选字段/类的每个字段创建一个空/null构造函数,以避免在反序列化时在avro模式中丢失字段。这样你就不会在特定类的可选字段中传递任何值,另一方面,满足模式字段,以便反序列化程序检查并满足根据定义的模式没有丢失任何内容。

ttvkxqim

ttvkxqim2#

不要错过avro架构avsc文件中使用的任何字段或类,即使它是可选的。只需使用null值进行序列化,以满足序列化时的架构形成,因为反序列化程序将查找 backbone ,如果缺少任何内容,它将失败。

相关问题