我正在编写一个工具,使用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
谢谢,
托马斯
答案 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。