Avro 字段默认值
Posted
技术标签:
【中文标题】Avro 字段默认值【英文标题】:Avro field default values 【发布时间】:2014-05-21 05:07:20 【问题描述】:我在为 Avro 字段设置默认值时遇到了一些问题。我有一个简单的架构,如下所示:
data.avsc:
"namespace":"test",
"type":"record",
"name":"Data",
"fields":[
"name": "id", "type": [ "long", "null" ] ,
"name": "value", "type": [ "string", "null" ] ,
"name": "raw", "type": [ "bytes", "null" ]
]
我正在使用 avro-maven-plugin v1.7.6 来生成 Java 模型。
当我使用以下方法创建模型实例时:
Data data = Data.newBuilder().build();
,失败并出现异常:
org.apache.avro.AvroRuntimeException: org.apache.avro.AvroRuntimeException:字段 id 类型:UNION pos:0 not 设置并且没有默认值。
但如果我指定“默认”属性,
"name": "id", "type": [ "long", "null" ], "default": "null" ,
我没有收到此错误。我在文档中读到联合中的第一个模式成为默认模式。所以我的问题是,为什么我还需要指定“默认”属性?还有什么方法可以使字段成为可选字段?
如果我确实需要指定默认值,这对联合有什么作用?我需要为联合中的每个架构指定默认值吗?这在顺序/语法方面是如何工作的?
谢谢。
【问题讨论】:
【参考方案1】:联合的默认值对应于联合的第一个模式 (Source)。您的联合定义为["long", "null"]
,因此默认值必须是长数字。 null
不是一个长数字,这就是您收到错误的原因。
如果您仍想将 null
定义为默认值,请先放置 null 架构,即将联合更改为 ["null", "long"]
。
【讨论】:
简单地将 null 放在类型联合中并不会使它看起来是可选的 - 这就是我拥有它但仍然得到错误的方式。至少在我使用的 Avro 1.7.5 上需要添加默认 null。 检查这个:bytepadding.com/big-data/spark/avro/…。具有完整的模式定义和字段规则表。涵盖所有默认的复杂类型。仅缺少 'record' 字段类型,但应用相同:"type": ["null", "name": "", "type":"record", "fields":[]]跨度> 这是 Avro 的一个非常令人惊讶的行为。我希望这个错误更明确【参考方案2】:它是 Avro 末尾的一个 错误,标记为 Not A Problem
。
您需要添加默认属性来提及默认值。
"name": "xxx", "type": ["null", "boolean"], "default": null
请参考AVRO-1803。
【讨论】:
对于数值,默认值必须为 null,但当为字符串类型时,它必须为“null” - 即“default”:null 和“default”:“null” 字节的默认值是多少? 我不会将此称为 Avro 中的错误。你可能会说这是一个糟糕的设计,而且它对某些人来说绝对不直观,但它是一个有意的特性,与 Avro 中的其他规则一致。在“this can be null”和“this can be null,并且可以完全丢失,在这种情况下它被假定为null”之间存在概念和字节级别的差异。 Avro 的标准只要求在模式中明确表达这种差异,而不是定义隐式默认值。【参考方案3】:您必须在架构中提供 "default": null
而不是 "default": "null"
才能使构建器方法正常工作
【讨论】:
【参考方案4】:我认为问题在于您正在使用构建器,
根据Java API的documentation:
使用构建器需要设置所有字段,即使它们为空
【讨论】:
以上是关于Avro 字段默认值的主要内容,如果未能解决你的问题,请参考以下文章
为啥 kafka-avro-console-producer 不遵守该字段的默认值?
如何在Avro Union逻辑类型字段中指定转换器的默认值?