当前位置: 首页 > 知识库问答 >
问题:

如果Avro模式中包含union,如何将json对象转换为Avro对象

高夜洛
2023-03-14

给定的示例模式包含一个字段,该字段是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用下面描述的代码snppet试了一下,

    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)

共有3个答案

华森
2023-03-14

有一个新的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

弘阳德
2023-03-14

查看此项目:https://github.com/allegro/hermes/pull/749/files

您对JsonAvroConverter感兴趣。它从json(没有联合类型)反序列化为Avro生成的对象(有联合类型)。实际上,它从union上的类型模式中获取并逐个尝试它们。它在我们的情况下非常有效。

这就是工作:https://github.com/allegro/json-avro-converter/blob/master/converter/src/main/java/tech/allegro/schema/json2avro/converter/JsonGenericRecordReader.java

问候!

孟璞
2023-03-14

如果可以选择使用node.js,则可以使用avsc为您进行转换。使用wrapUnions设置调用clone将自动将值包装到它们匹配的第一个联合分支中。

使用您的示例:

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"
// }
 类似资料:
  • 有一个网站这样做,但我想要一个图书馆或CLI。 谢了!

  • 如何使用用户指定的架构将dataframe转换为Avro格式?

  • 使用字符串数组为对象创建avro模式的正确方法是什么? 我试图创建avro模式的对象,有字符串数组根据官方文档?但我得到错误。 https://avro.apache.org/docs/1.8.1/spec.html [错误]无法执行目标组织。阿帕奇。avro:avro maven插件:1.8.2:项目电子邮件上的模式(默认值):目标组织的执行默认值。阿帕奇。avro:avro maven插件:1

  • 问题内容: 我正在使用org.json库将Object转换为Json格式。请检查以下代码片段。 它显示了这样的输出: 它显示为空白并添加了卷曲基数。这是什么意思?有人遇到过这个问题吗? 问题答案: 首先,我强烈建议您不要使用此库(org.json),这是一个非常古老且不受支持的库(据我所知)。我建议杰克逊或格森。 但是,如果您确实需要JSONObject,则可以将getter添加到枚举中: 序列化

  • 我有一个字符串(jsonData)通过Jackson对象映射器映射到json,如下所示,映射到JaxB。 我能够很好地映射到上面的字符串。然而,我在映射到jooq JSON对象时遇到了问题。我想我现在必须将jsonData转换为jooq JSON。 我该怎么做? 或者我必须创建某种包装? 由jooq配置的DTO

  • 问题内容: 有没有一种方法可以在不使用Python定义架构的情况下将JSON字符串转换为Avro?还是只有Java才能处理的事情? 问题答案: Apache Avro™1.7.6入门(Python) :