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。
我正在编写一个工具,使用 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。