Avro Json.ObjectWriter - “不是Json架构”错误

时间:2016-02-24 23:31:34

标签: json avro

我正在编写一个工具,使用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但没有成功(除了空格和换行符,它们是相同的)。用org.apache.avro.data.Json.SCHEMA而不是mySchema初始化jsonEncoder也没有改变任何东西。使用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.ObjectWriter的模式会导致org.apache.avro.data.Json.write(Json.java:183)中的NullPointerException(这是一种不推荐使用的方法)。

从盯着org.apache.avro.data.Json.java看来,我觉得Avro正在检查我的记录架构,而不是它自己的Json记录架构(第58行)是否相等(第73行)。

{"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"}
      ]
     }
 ]
}

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

equals

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); } } 在org.apache.avro.Schema中实现,第346行:

<div class="control-group"> 
    <%= f.label :paper_type, class: 'control-label' %><br>
        <div class="controls">
            <%= f.select(:paper_type, options_for_select([['Skrifstofupappír', 'Skrifstofupappír'], ['Dagblaðapappír', 'Dagblaðapappír'], ['Glans_&_tímaritapappír', 'Glans_&_tímaritapappír'], ['Annað', 'Annað']])) %>
      </div>
</div>  


<div class="control-group"> 
    <%= f.label :paper_weight, class: 'control-label' %><br>
        <div class="controls">
            <%= f.number_field :paper_weight %>
        </div>
</div>  

我不完全理解第三次检查中发生了什么(特别是equalCachedHash()),但我只是认识到对平等的检查,这对我来说没有意义。

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

完整来源位于https://github.com/tomlurge/converTor

谢谢,
托马斯

1 个答案:

答案 0 :(得分:0)

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

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