在阅读avro文档时,例如[1],我了解到,支持模式演化,如果我添加了具有指定默认值的列,它应该是向后兼容的(当我再次删除它时,甚至是向前兼容的)。听起来不错,所以我添加了一个列,定义为:
{
"name": "newColumn",
"type": ["null","string"],
"default": null,
"doc": "something wrong"
}
并尝试从一开始就使用具有此架构的某个主题,它失败并显示消息:
Caused by: java.lang.ArrayIndexOutOfBoundsException: 5
at org.apache.avro.io.parsing.Symbol$Alternative.getSymbol(Symbol.java:424)
at org.apache.avro.io.ResolvingDecoder.doAction(ResolvingDecoder.java:290)
at org.apache.avro.io.parsing.Parser.advance(Parser.java:88)
at org.apache.avro.io.ResolvingDecoder.readIndex(ResolvingDecoder.java:267)
at org.apache.avro.generic.GenericDatumReader.readWithoutConversion(GenericDatumReader.java:179)
at org.apache.avro.generic.GenericDatumReader.read(GenericDatumReader.java:153)
at org.apache.avro.generic.GenericDatumReader.readField(GenericDatumReader.java:232)
at org.apache.avro.generic.GenericDatumReader.readRecord(GenericDatumReader.java:222)
at org.apache.avro.generic.GenericDatumReader.readWithoutConversion(GenericDatumReader.java:175)
at org.apache.avro.generic.GenericDatumReader.read(GenericDatumReader.java:153)
at org.apache.avro.generic.GenericDatumReader.readWithoutConversion(GenericDatumReader.java:179)
at org.apache.avro.generic.GenericDatumReader.read(GenericDatumReader.java:153)
at org.apache.avro.generic.GenericDatumReader.readField(GenericDatumReader.java:232)
at org.apache.avro.generic.GenericDatumReader.readRecord(GenericDatumReader.java:222)
at org.apache.avro.generic.GenericDatumReader.readWithoutConversion(GenericDatumReader.java:175)
at org.apache.avro.generic.GenericDatumReader.read(GenericDatumReader.java:153)
at org.apache.avro.generic.GenericDatumReader.read(GenericDatumReader.java:145)
at tech.allegro.schema.json2avro.converter.JsonAvroConverter.convertToJson(JsonAvroConverter.java:83)
提供更多的信息。Avro模式定义了一个顶级类型,具有2个字段。描述消息类型的字符串,以及N种类型的并集。可以读取所有N-1个未修改的类型,但是不能读取用可选的default-having列更新的类型。我不确定这个设计严格来说是否正确,但这不是重点(请随意批评并推荐更好的方法!).我在追求模式进化,这似乎行不通。
我做错什么了吗?
[1] https://docs.oracle.com/database/nosql-12.1.3.4/GettingStartedGuide/schemaevolution.html#changeschema-规则
编辑:如果我们将类型定义更改为:
"type": "string",
"default": ""
它仍然不工作,生成的错误是:
Caused by: org.apache.avro.AvroRuntimeException: Malformed data. Length is negative: -1
at org.apache.avro.io.BinaryDecoder.doReadBytes(BinaryDecoder.java:336)
at org.apache.avro.io.BinaryDecoder.readString(BinaryDecoder.java:263)
at org.apache.avro.io.ResolvingDecoder.readString(ResolvingDecoder.java:201)
at org.apache.avro.generic.GenericDatumReader.readString(GenericDatumReader.java:422)
at org.apache.avro.generic.GenericDatumReader.readString(GenericDatumReader.java:414)
at org.apache.avro.generic.GenericDatumReader.readWithoutConversion(GenericDatumReader.java:181)
at org.apache.avro.generic.GenericDatumReader.read(GenericDatumReader.java:153)
at org.apache.avro.generic.GenericDatumReader.readField(GenericDatumReader.java:232)
at org.apache.avro.generic.GenericDatumReader.readRecord(GenericDatumReader.java:222)
at org.apache.avro.generic.GenericDatumReader.readWithoutConversion(GenericDatumReader.java:175)
at org.apache.avro.generic.GenericDatumReader.read(GenericDatumReader.java:153)
at org.apache.avro.generic.GenericDatumReader.readWithoutConversion(GenericDatumReader.java:179)
at org.apache.avro.generic.GenericDatumReader.read(GenericDatumReader.java:153)
at org.apache.avro.generic.GenericDatumReader.readField(GenericDatumReader.java:232)
at org.apache.avro.generic.GenericDatumReader.readRecord(GenericDatumReader.java:222)
at org.apache.avro.generic.GenericDatumReader.readWithoutConversion(GenericDatumReader.java:175)
at org.apache.avro.generic.GenericDatumReader.read(GenericDatumReader.java:153)
at org.apache.avro.generic.GenericDatumReader.read(GenericDatumReader.java:145)
at tech.allegro.schema.json2avro.converter.JsonAvroConverter.convertToJson(JsonAvroConverter.java:83)
什么代码会导致给定的失败:
BinaryDecoder binaryDecoder = DecoderFactory.get().binaryDecoder(avro, (BinaryDecoder)null);
GenericRecord record = (GenericRecord)(new GenericDatumReader(schema)).read((Object)null, binaryDecoder);
对于模式演化及其工作原理,通常存在一些误解。当您演化模式时,并不意味着您不需要“编写器”模式来读取avro数据。为此,您应该使用以下构造函数:GenericDatumReader
public GenericDatumReader(Schema writer,
Schema reader)
如您所见,编写器模式(用于序列化avro数据的模式)和读取器模式(您的“演进”模式)必须存在。有几个库/工具(Hive、Spark)对此进行了抽象,但这只是因为文件本身包含模式(无模式)
我有2个模式: 模式1(旧模式): 我用一个布尔字段更新了模式: 方案2(新方案): kafka主题包含属于旧模式(schema1)的消息。更新使用者模式后,即使更新字段中存在默认值,使用者也无法反序列化旧模式消息。 根据Avro文档: 阿夫罗博士 我得到以下错误,而反序列化: 当记录缺少字段时,为什么默认值未应用于使用者?任何帮助都非常感谢。提前致谢!
我有以下对象: Bu 有时我只是我正在尝试为此提出一个架构。但它似乎:(不起作用。 我尝试了以下两种: 但它失败了,线程“main”org.apache.avro中出现<code>异常。SchemaParseException:无类型: 我也尝试了同样的错误: 我真的不明白问题出在哪里,两者有什么区别。
我尝试使用以下代码反序列化API中接收的JSON对象: 我的类使用Lombok生成构造函数、getter和setter,如下所示: 这两个属性都应该是可选的,如果没有提供,则使用类定义中指定的默认值。但是,如果我现在尝试反序列化JSON 字段为。根据我的理解,以及我找到的所有示例代码,应该是一个空列表。 编辑:不是重复的,因为我使用的是没有选项的Lombok
问题内容: 我正在寻找将列添加到默认值为0的MySQL数据库的语法 参考 问题答案: 尝试这个: 从链接到的文档中: 要在页面下方查找搜索语法,请执行以下操作: column_definition子句对ADD和CHANGE使用与CREATE TABLE相同的语法。请参见第12.1.17节“创建表语法”。 并从链接页面: 注意那里的DEFAULT这个词。
我在两个独立的AVCS模式文件中定义了记录的两个版本。我使用命名空间来区分版本SimpleV1.avsc 示例JSON 版本2只是有一个带有默认值的附加描述字段。 SimpleV2.avsc 示例JSON 这两个模式都序列化为Java类。在我的示例中,我将测试向后兼容性。V1写入的记录应由使用V2的读取器读取。我希望看到插入默认值。只要我不使用枚举,这就可以工作。 检查读者作家兼容性方法确认模式是
Jackson可以在2.6.5中为以下类反序列化json,但在2.8.8中失败。 型号: JSON: 例外情况是: 我发现lombok创建的子构造函数导致了这个错误。当我去掉lombok注释或手动创建构造函数时,这种情况就会停止。无论如何,它都应该使用no args Child()构造函数。是什么导致了这个问题?