Avro Json.ObjectWriter - "Not the Json schema" 错误

Avro Json.ObjectWriter - "Not the Json schema" error

我正在编写一个工具,使用 Avro 1.8.0 将数据从本地格式转换为 Avro、JSON 和 Parquet。转换为 Avro 和 Parquet 工作正常,但 JSON 转换会引发以下错误:

Exception in thread "main" java.lang.RuntimeException: Not the Json schema:
{"type":"record","name":"Torperf","namespace":"converTor.torperf",
"fields":[{"name":"descriptor_type","type":"string"," 
[... rest of the schema omitted for brevity]

令人恼火的是,这是我传递的架构,我确实希望转换器使用它。我不知道 Avro 在抱怨什么。 这是我的代码的相关片段:

//  parse the schema file
Schema.Parser parser = new Schema.Parser();
Schema mySchema;
//  tried two ways to load the schema
//  like this
File schemaFile = new File("myJsonSchema.avsc");
mySchema = parser.parse(schemaFile) ;
//  and also like Json.class loads it's schema
mySchema = parser.parse(Json.class.getResourceAsStream("myJsonSchema.avsc"));

//  initialize the writer
Json.ObjectWriter jsonDatumWriter = new Json.ObjectWriter();
jsonDatumWriter.setSchema(mySchema);
OutputStream out = new FileOutputStream(new File("output.avro"));
Encoder encoder = EncoderFactory.get().jsonEncoder(mySchema, out);

//  append a record created by way of a specific mapping
jsonDatumWriter.write(specificRecord, encoder);

我用从异常返回的那个替换了 myJsonSchema.avsc 但没有成功(除了空格和换行符,它们是相同的)。使用 org.apache.avro.data.Json.SCHEMA 而不是 mySchema 初始化 jsonEncoder 也没有改变任何东西。将传递给 Json.ObjectWriter 的模式替换为 org.apache.avro.data.Json.SCHEMA 会导致 NullPointerException 在 org.apache.avro.data.Json.write(Json.java:183)(这是一种已弃用的方法)。

从盯着 org.apache.avro.data.Json.java 开始,在我看来,Avro 正在检查我的记录模式与它自己的 Json 记录模式(第 58 行)是否相等(第 73 行)。

58  SCHEMA = Schema.parse(Json.class.getResourceAsStream("/org/apache/avro/data/Json.avsc"));

72  public void setSchema(Schema schema) {
73    if(!Json.SCHEMA.equals(schema))
74      throw new RuntimeException("Not the Json schema: " + schema);
75  }

引用的Json.avsc定义了一条记录的字段类型:

{"type": "record", "name": "Json", "namespace":"org.apache.avro.data",
 "fields": [
     {"name": "value",
      "type": [
          "long",
          "double",
          "string",
          "boolean",
          "null",
          {"type": "array", "items": "Json"},
          {"type": "map", "values": "Json"}
      ]
     }
 ]
}

equals在org.apache.avro.Schema中实现,第346行:

  public boolean equals(Object o) {
    if(o == this) {
      return true;
    } else if(!(o instanceof Schema)) {
      return false;
    } else {
      Schema that = (Schema)o;
      return this.type != that.type?false:this.equalCachedHash(that) && this.props.equals(that.props);
    }
  }

我不完全理解第三次检查(尤其是 equalCachedHash())中发生的事情,但我只以一种对我来说没有意义的微不足道的方式识别相等性检查。

此外,我在 InterWebs 上找不到任何关于 Avro Json.ObjectWriter 用法的示例或说明。我想知道我是否应该使用已弃用的 Json.Writer,因为至少有一些在线代码片段可供学习和收集。

完整的源代码可在 https://github.com/tomlurge/converTor

谢谢,
托马斯

更多的调试证明将 org.apache.avro.data.Json.SCHEMA 传递给 Json.ObjectWriter 确实是正确的做法。我写回 System.out 的对象打印出我期望的 JSON 对象。空指针异常并没有消失。 可能我根本不需要 Json.ObjectWriter 的 setSchema(),因为完全省略命令会导致相同的 NullPointerException。

我终于向 Avro 提交了一个错误,结果发现在我的代码中我将一个 "specific" 类型的对象交给了它无法处理的 ObjectWriter。它 return 默默地做了,只是在稍后阶段才抛出错误。这已在 Avro 1.8.1 中修复 - 详情请参阅 https://issues.apache.org/jira/browse/AVRO-1807