我有一个已更新为包含新字段的架构。我正在使用avro反射和融合的架构注册表对数据进行反序列化/序列化,如下所示:
序列化:
Schema schema = REFLECT_DATA.getSchema(value.getClass());
try {
int registeredSchemaId = this.schemaRegistry.register(subject, schema);
ByteArrayOutputStream out = new ByteArrayOutputStream();
out.write(0);
out.write(ByteBuffer.allocate(4).putInt(registeredSchemaId).array());
DatumWriter<Object> dw = new ReflectDatumWriter<>(schema);
Encoder encoder = ENCODER_FACTORY.directBinaryEncoder(out, null);
dw.write(value, encoder);
encoder.flush();
return out.toByteArray();
} catch (RuntimeException | IOException e) {
throw new SerializationException("Error serializing Avro message", e);
} catch (RestClientException e) {
throw new SerializationException("Error registering Avro schema: " + schema, e);
}
反序列化:
if (readerSchema == null) {
readerSchema = new Schema.Parser().parse(schemaString);
}
int schemaId = -1;
try {
ByteBuffer buffer = ByteBuffer.wrap(payload);
if (buffer.get() != MAGIC_BYTE) {
throw new SerializationException("Unknown magic byte!");
}
schemaId = buffer.getInt();
Schema writerSchema = schemaRegistry.getById(schemaId);
int start = buffer.position() + buffer.arrayOffset();
int length = buffer.limit() - 1 - idSize;
DatumReader<Object> reader = new ReflectDatumReader<>(writerSchema, readerSchema);
BinaryDecoder decoder = decoderFactory.binaryDecoder(buffer.array(), start, length, null);
return reader.read(null, decoder); //line 83
} catch (IOException e) {
throw new SerializationException("Error deserializing Avro message for id " + schemaId, e);
} catch (RestClientException e) {
throw new SerializationException("Error retrieving Avro schema for id " + schemaId, e);
}
该模式由一个scala case类定义,旧的类如下:
case class Data(oldField: String) {
def this("")
}
它已经像这样更新了:
case class Data(oldField: String, @AvroDefault("") newField: String) {
def this("", "")
}
但是,反序列化有时会在以下堆栈中抛出AvroTypeException:
Caused by: org.apache.avro.AvroTypeException: Found com.company.project.DataHolder$.Data, expecting com.company.project.DataHolder$.Data
at org.apache.avro.io.ResolvingDecoder.doAction(ResolvingDecoder.java:231)
at org.apache.avro.io.parsing.Parser.advance(Parser.java:88)
at org.apache.avro.io.ResolvingDecoder.readFieldOrder(ResolvingDecoder.java:127)
at org.apache.avro.generic.GenericDatumReader.readRecord(GenericDatumReader.java:173)
at org.apache.avro.generic.GenericDatumReader.read(GenericDatumReader.java:148)
at org.apache.avro.generic.GenericDatumReader.read(GenericDatumReader.java:139)
at io.fama.pubsub.KafkaAvroReflectDeserializer.deserialize(KafkaAvroReflectDeserializer.java:83)
我认为这是由于序列化旧邮件时遇到的困难(但我不能完全确定-我只是无法推断出它还有什么可能)。有没有其他人遇到过此错误,或者没有人有解决此错误的想法?
答案 0 :(得分:1)
如果您使用的是org.apache.avro.reflect属性,那么我认为您不能使用Scala案例类-Scala案例类参数是不可变的,我相信属性映射器将需要有一个类具有公共的空构造函数和Java可见字段,甚至@BeanProperty都可以生成Java setters / getters。