【发布时间】:2018-02-01 19:44:09
【问题描述】:
场景 - 客户端使用 Avro Reflect Datum Writer 序列化 POJO,并将 GenericRecord 写入文件。 通过反射得到的schema是这样的(注意顺序A、B、D、C)——
{
"namespace": "storage.management.example.schema",
"type": "record",
"doc": "Example schema for testing",
"name": "Event",
"fields": [
....
....
{ "name": "A", "type": "string" },
{ "name": "B", "type": "string" },
{ "name": "D", "type": "string" },
{ "name": "C", "type": "string" },
....
....
]
}
代理读取文件并使用默认模式(注意排序 - A、B、C、D)来反序列化记录的子集(保证客户端具有这些字段)
{
"namespace": "storage.management.example.schema",
"type": "record",
"doc": "Example schema for testing",
"name": "Event",
"fields": [
{ "name": "A", "type": "string" },
{ "name": "B", "type": "string" },
{ "name": "C", "type": "string" },
{ "name": "D", "type": "string" }
]
}
问题: 使用上述子集模式进行反序列化会导致以下异常 -
Caused by: java.io.IOException: Invalid int encoding
at org.apache.avro.io.BinaryDecoder.readInt(BinaryDecoder.java:145)
at org.apache.avro.io.BinaryDecoder.readString(BinaryDecoder.java:259)
at org.apache.avro.io.ResolvingDecoder.readString(ResolvingDecoder.java:201)
at org.apache.avro.generic.GenericDatumReader.readString(GenericDatumReader.java:430)
at org.apache.avro.generic.GenericDatumReader.readString(GenericDatumReader.java:422)
at org.apache.avro.generic.GenericDatumReader.readWithoutConversion(GenericDatumReader.java:180)
at org.apache.avro.generic.GenericDatumReader.read(GenericDatumReader.java:152)
at org.apache.avro.generic.GenericDatumReader.readField(GenericDatumReader.java:240)
at org.apache.avro.generic.GenericDatumReader.readRecord(GenericDatumReader.java:230)
但是,如果子模式还按 A、B、D、C 的顺序指定字段,则反序列化成功。(与客户端模式相同)
这是预期的行为吗?我虽然 Avro 只依赖于字段名称来构建记录而不是排序。
对此有任何修复吗?不同的客户端可能有不同的顺序,我无法强制执行顺序,因为架构是通过反射生成的。
【问题讨论】:
-
您使用的是 BinaryDecoder 吗?如果是这样,请尝试使用 DataFileReader。
import org.apache.avro.file.DataFileReader