【问题标题】:Avro Json.ObjectWriter - "Not the Json schema" errorAvro Json.ObjectWriter - “不是 Json 模式”错误
【发布时间】:2016-02-24 23:31:34
【问题描述】:

我正在编写一个工具,使用 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 在抱怨什么。 这是我的代码的相关sn-p:

//  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 会导致 org.apache.avro.data.Json.write(Json.java:183) 处出现 NullPointerException(这是一个已弃用的方法)。

从盯着 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,因为至少有一些在线代码 sn-ps 可供学习和收集。

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

谢谢,
托马斯

【问题讨论】:

    标签: json avro


    【解决方案1】:

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

    我终于向 Avro 提交了一个错误,结果发现在我的代码中我将一个“特定”类型的对象交给了它无法处理的 ObjectWriter。它确实默默地返回,并且仅在稍后阶段引发错误。这已在 Avro 1.8.1 中修复 - 有关详细信息,请参阅 https://issues.apache.org/jira/browse/AVRO-1807

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-09-05
      • 1970-01-01
      • 1970-01-01
      • 2016-08-09
      • 2020-11-26
      • 2020-11-09
      • 2021-12-08
      • 2020-01-17
      相关资源
      最近更新 更多