给定示例模式包含一个字段,该字段是null和string的结合,
{
"type":"record",
"name":"DataFlowEntity",
"namespace":"org.sdf.manage.commons.server",
"fields":
[
{"name":"dataTypeGroupName","type":["null","string"]},
{"name":"dataTypeName","type":"string"},
{"name":"dataSchemaVersion","type":"string"}
]
}
我想转换以下json对象,
{
"dataTypeGroupName": "dg_1",
"dataTypeName": "dt_1",
"dataSchemaVersion": "1"
}
到与上述模式对应的avro对象中。 我尝试使用Avro的JsonDecoder和下面描述的代码snipet,
String dataFlowEntity = "{\"dataTypeGroupName\": \"dg_1\", \"dataTypeName\": \"dt_1\", \"dataSchemaVersion\": \"1\"}";
Schema schema = DataFlowEntity.SCHEMA$;
InputStream inputStream = new ByteArrayInputStream(dataFlowEntity.getBytes());
DataInputStream dInputStream = new DataInputStream(inputStream);
Decoder decoder = DecoderFactory.get().jsonDecoder(schema, dInputStream);
DatumReader<DataFlowEntity> datumReader = new GenericDatumReader<DataFlowEntity>(schema);
DataFlowEntity dataFlowEntityObject = DataFlowEntity.newBuilder().build();
dataFlowEntityObject = datumReader.read(null, decoder);
失败,例外,
threw exception [org.apache.avro.AvroRuntimeException: org.apache.avro.AvroRuntimeException: Field dataTypeGroupName type:UNION pos:0 not set and has no default value] with root cause
org.apache.avro.AvroRuntimeException: Field dataTypeGroupName type:UNION pos:0 not set and has no default value
at org.apache.avro.generic.GenericData.getDefaultValue(GenericData.java:874)
at org.apache.avro.data.RecordBuilderBase.defaultValue(RecordBuilderBase.java:135)
答案 0 :(得分:2)
如果使用node.js是一个选项,您可以使用avsc
为您进行转换。使用wrapUnions
set调用clone
会自动将值包装到它们匹配的第一个union分支中。
使用您的示例:
var avsc = require('avsc');
var type = avsc.parse({
"type":"record",
"name":"DataFlowEntity",
"namespace":"org.sdf.manage.commons.server",
"fields": [
{"name":"dataTypeGroupName","type":["null","string"]},
{"name":"dataTypeName","type":"string"},
{"name":"dataSchemaVersion","type":"string"}
]
}, {wrapUnions: true});
var invalidRecord = {
"dataTypeGroupName": "dg_1",
"dataTypeName": "dt_1",
"dataSchemaVersion": "1"
};
var validRecord = type.clone(invalidRecord, {wrapUnions: true});
// == {
// "dataTypeGroupName":{"string":"dg_1"},
// "dataTypeName":"dt_1",
// "dataSchemaVersion":"1"
// }
答案 1 :(得分:0)
有一个新的JSON编码器正在解决这个常见问题:
https://issues.apache.org/jira/browse/AVRO-1582
https://github.com/zolyfarkas/avro
这似乎是很多人在与Avro打交道时遇到的常见问题。
如果你将JSON切换到它,它应该可以工作:
{
"dataTypeGroupName": {"string" : "dg_1"},
"dataTypeName": "dt_1",
"dataSchemaVersion": "1"
}
这是因为Avro使用对象类型包装器对联合进行编码,遗憾的是,甚至是简单的联合来表示不需要JSON对象包装器来消除歧义的可选类型。 Avro的意图似乎永远不会生成友好的JSON,更多的是使用JSON作为序列化格式。
了解更多详情: https://avro.apache.org/docs/1.7.7/spec.html#json_encoding
答案 2 :(得分:0)
检出该项目:https://github.com/allegro/hermes/pull/749/files
您对JsonAvroConverter感兴趣。它从json(无联合类型)反序列化为Avro生成的对象(具有联合类型)。实际上,它是从并集上的类型模式获得的,并一一尝试。在我们的情况下,效果很好。
致谢!