簡體   English   中英

如果avro架構中包含union,如何將json對象轉換為Avro對象

[英]How to convert a json object into Avro object if avro schema contains union in it

給定示例模式包含一個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)

如果使用node.js是一個選項,您可以使用avsc為您進行轉換。 使用wrapUnions設置調用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"
// }

工作中有一個新的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

檢查這個項目: 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

問候!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM