java—在avro模式中使用“default”

kuarbcqp  于 2021-05-29  发布在  Hadoop
关注(0)|答案(1)|浏览(807)

根据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编译器从学生模式自动生成)

rqmkfv5c

rqmkfv5c1#

我认为对默认值有一些误解,所以希望我的解释也能对其他人有所帮助。当字段不存在时,缺省值对于提供缺省值很有用,但这基本上是在示例化avro对象时(在您的示例中是调用 datumReader.read )但是它不允许用不同的模式读取数据,这就是为什么“模式注册表”的概念在这种情况下是有用的。
下面的代码可以工作并允许读取数据

Decoder decoder = DecoderFactory.get().jsonDecoder(Student.SCHEMA$, "{\"age\":70}");
SpecificDatumReader<Student> datumReader = new SpecificDatumReader<>(Student.class);

Schema expected = new Schema.Parser().parse("{\n" +
        "  \"type\": \"record\",\n" +
        "  \"namespace\": \"com.example\",\n" +
        "  \"name\": \"Student\",\n" +
        "  \"fields\": [{\n" +
        "    \"name\": \"age\",\n" +
        "    \"type\": \"int\",\n" +
        "    \"default\": -1\n" +
        "  }\n" +
        "  ]\n" +
        "}");

datumReader.setSchema(expected);
System.out.println(datumReader.read(null, decoder));

如您所见,我正在指定用于“写入”json输入的模式,该模式不包含字段“name”,但是(考虑到您的模式包含默认值),当您打印记录时,您将看到具有默认值的名称

{"age": 70, "name": "null"}

以防万一,可能知道也可能不知道,“null”不是一个真正的null值,而是一个值为“null”的字符串。

相关问题