【发布时间】: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
谢谢,
托马斯
【问题讨论】: