根据avro文档中“default”属性的定义:“此字段的默认值,在读取缺少此字段的示例时使用(可选)。”
这意味着如果缺少相应的字段,则采用默认值。
但事实似乎并非如此。考虑以下几点 student
架构:
{
"type": "record",
"namespace": "com.example",
"name": "Student",
"fields": [{
"name": "age",
"type": "int",
"default": -1
},
{
"name": "name",
"type": "string",
"default": "null"
}
]
}
模式表示:如果缺少“age”字段,则将值视为-1。“name”字段也是如此。
现在,如果我尝试从以下json构建学生模型:
{"age":70}
我有个例外:
org.apache.avro.AvroTypeException: Expected string. Got END_OBJECT
at org.apache.avro.io.JsonDecoder.error(JsonDecoder.java:698)
at org.apache.avro.io.JsonDecoder.readString(JsonDecoder.java:227)
看起来默认设置没有按预期工作。那么,违约在这里到底扮演什么角色呢?
这是用于生成学生模型的代码:
Decoder decoder = DecoderFactory.get().jsonDecoder(Student.SCHEMA$, studentJson);
SpecificDatumReader<Student> datumReader = new SpecificDatumReader<>(Student.class);
return datumReader.read(null, decoder);
( Student
类由avro编译器从学生模式自动生成)
1条答案
按热度按时间rqmkfv5c1#
我认为对默认值有一些误解,所以希望我的解释也能对其他人有所帮助。当字段不存在时,缺省值对于提供缺省值很有用,但这基本上是在示例化avro对象时(在您的示例中是调用
datumReader.read
)但是它不允许用不同的模式读取数据,这就是为什么“模式注册表”的概念在这种情况下是有用的。下面的代码可以工作并允许读取数据
如您所见,我正在指定用于“写入”json输入的模式,该模式不包含字段“name”,但是(考虑到您的模式包含默认值),当您打印记录时,您将看到具有默认值的名称
以防万一,可能知道也可能不知道,“null”不是一个真正的null值,而是一个值为“null”的字符串。