我正在尝试与salesforces集成新的grpc更改数据捕获事件总线。事件通过grpc发送给客户端,并带有avro编码的消息,说明对记录的更改,因此客户端必须使用提供且无法更改的avro模式对消息进行解码。
对于具有两种联合类型字段的对象,我能够轻松解码avro编码的消息,但具有三种类型的字段会引发异常。
这是Account avro模式的Name字段:
{ "name": "Name", "type": [ "null", "string", { "type": "record", "name": "Switchable_PersonName", "fields": [ { "name": "Salutation", "type": [ "null", "string" ], "default": null }, { "name": "FirstName", "type": [ "null", "string" ], "default": null }, { "name": "LastName", "type": [ "null", "string" ], "default": null }, { "name": "MiddleName", "type": [ "null", "string" ], "default": null }, { "name": "InformalName", "type": [ "null", "string" ], "default": null }, { "name": "Suffix", "type": [ "null", "string" ], "default": null } ] } ], "doc": "Data:Switchable_PersonName", "default": null },
正如您所看到的,名称可以是null、字符串或名为Switchable_PersonName的对象。
使用avrogen-cli工具,我能够将avro模式转换为AccountChangeEvent、ChangeEventHeader、ChangeType、Address、Switchable_PersonName的具体c#类。AccountChangeEvent类中的Name字段创建为:
private object _Name;
这是我对avro消息进行解码的方法:
public static void DeserializeAccountConcrete(byte[] payload) { var accSchema = Avro.Schema.Parse(File.ReadAllText("./avro/AccountGRPCSchema.avsc")); var unionSchema = accSchema as Avro.UnionSchema; var cache = new ClassCache(); cache.LoadClassCache(typeof(AccountChangeEvent), unionSchema); cache.LoadClassCache(typeof(Switchable_PersonName), unionSchema); cache.LoadClassCache(typeof(Address), unionSchema); var reader = new ReflectReader<AccountChangeEvent>(accSchema, accSchema, cache); using var accStream = new MemoryStream(payload); accStream.Seek(0, SeekOrigin.Begin); var accDecoder = new BinaryDecoder(accStream); var accEvent = reader.Read(accDecoder); Console.WriteLine(accEvent.Name); Console.WriteLine("Event " + accEvent.ChangeEventHeader.changeType); }
这种反序列化对其他架构有效,但对Account架构失败,引发此异常。
Avro.AvroException:联合记录类型com.sface.eventbus.Switchable_PersonName的类未注册。请创建ClassCache对象并调用LoadClassCache
查看avro的文档,我的实现看起来是正确的,但似乎不是。
我已将字段类型更改为
private com.sforce.eventbus.Switchable_PersonName _Name;
以及可能依赖于此字段的任何其他代码,但仍然会抛出相同的错误。我是avro的新手,因此可能有很多事情我不知道或做得不对。