【发布时间】:2014-04-08 14:01:52
【问题描述】:
我正在尝试编写一个非常简单的 avro 模式(很简单,因为我只是指出我当前的问题)来基于以 json 格式存储的数据编写一个 avro 数据文件。诀窍是一个字段是可选的,而 avrotools 或我中的一个没有做对。
目标不是编写我自己的序列化器,最终目标是把它放在水槽中,我处于早期阶段。
数据(作品),在名为 so.log 的文件中:
{
"valid": {"boolean":true}
, "source": {"bytes":"live"}
}
架构,在名为 so.avsc 的文件中:
{
"type":"record",
"name":"Event",
"fields":[
{"name":"valid", "type": ["null", "boolean"],"default":null}
, {"name":"source","type": ["null", "bytes"],"default":null}
]
}
我可以使用以下命令轻松生成 avro 文件:
java -jar avro-tools-1.7.6.jar fromjson --schema-file so.avsc so.log
到目前为止一切顺利。问题是“来源”是可选的,所以我希望以下数据也是有效的:
{
"valid": {"boolean":true}
}
但是运行相同的命令给了我错误:
Exception in thread "main" org.apache.avro.AvroTypeException: Expected start-union. Got END_OBJECT
at org.apache.avro.io.JsonDecoder.error(JsonDecoder.java:697)
at org.apache.avro.io.JsonDecoder.readIndex(JsonDecoder.java:441)
at org.apache.avro.io.ResolvingDecoder.doAction(ResolvingDecoder.java:229)
at org.apache.avro.io.parsing.Parser.advance(Parser.java:88)
at org.apache.avro.io.ResolvingDecoder.readIndex(ResolvingDecoder.java:206)
at org.apache.avro.generic.GenericDatumReader.read(GenericDatumReader.java:155)
at org.apache.avro.generic.GenericDatumReader.readField(GenericDatumReader.java:193)
at org.apache.avro.generic.GenericDatumReader.readRecord(GenericDatumReader.java:183)
at org.apache.avro.generic.GenericDatumReader.read(GenericDatumReader.java:151)
at org.apache.avro.generic.GenericDatumReader.read(GenericDatumReader.java:142)
at org.apache.avro.tool.DataFileWriteTool.run(DataFileWriteTool.java:99)
at org.apache.avro.tool.Main.run(Main.java:84)
at org.apache.avro.tool.Main.main(Main.java:73)
我确实在架构中尝试了很多变体,甚至是不遵循 avro 规范的东西。据我所知,我在这里展示的架构是规范所说的应该是什么。
有谁知道我做错了什么,以及如何在不编写自己的序列化程序的情况下实际拥有可选元素?
谢谢,
【问题讨论】:
-
在这里看到同样的问题,您是否找到了使用 AvroTools 将带有可选字段的 JSON 转换为 Avro 的方法?目前我能想到的唯一解决方法是编写一个包装器,在转换之前在 JSON 中插入默认值,但这很可惜......
-
遗憾的是我运气不佳。简而言之,JSON 只是为了方便,虽然模式可以有默认值,但缺少该值的 JSON 文档实际上是无效的。我记录了一些problems and solutions we had with avro,希望对您有所帮助。
-
感谢您的回答,我会阅读您的博客文章!我们暂时放弃了 JSON > Avro 转换。
-
Avro 文档说使用“构建器需要设置所有字段,即使它们为空”。可能和你的情况有关。检查avro.apache.org/docs/1.7.7/gettingstartedjava.html