2016-04-10 9 views
7

入れ子フィールドが1つしか変わらない2つの同様のスキーマがあります(スキーマ1ではonefield、スキーマ2ではanotherfieldと呼ばれます)。プログラムで2つのavroスキーマをマージする

SCHEMA1

{ 
    "type": "record", 
    "name": "event", 
    "namespace": "foo", 
    "fields": [ 
     { 
      "name": "metadata", 
      "type": { 
       "type": "record", 
       "name": "event", 
       "namespace": "foo.metadata", 
       "fields": [ 
        { 
         "name": "onefield", 
         "type": [ 
          "null", 
          "string" 
         ], 
         "default": null 
        } 
       ] 
      }, 
      "default": null 
     } 
    ] 
} 

SCHEMA2

{ 
    "type": "record", 
    "name": "event", 
    "namespace": "foo", 
    "fields": [ 
     { 
      "name": "metadata", 
      "type": { 
       "type": "record", 
       "name": "event", 
       "namespace": "foo.metadata", 
       "fields": [ 
        { 
         "name": "anotherfield", 
         "type": [ 
          "null", 
          "string" 
         ], 
         "default": null 
        } 
       ] 
      }, 
      "default": null 
     } 
    ] 
} 

私はプログラム的にアブロ1.8.0使用して両方のスキーマをマージすることができています:

Schema s1 = new Schema.Parser().parse(schema1); 
Schema s2 = new Schema.Parser().parse(schema2); 
Schema[] schemas = {s1, s2}; 

Schema mergedSchema = null; 
for (Schema schema: schemas) { 
    mergedSchema = AvroStorageUtils.mergeSchema(mergedSchema, schema); 
} 

をして変換するためにそれを使用します〜 {"metadata":{"onefield":null,"anotherfield":null}}:コードは、期待される出力を示すこと

JsonAvroConverter converter = new JsonAvroConverter(); 
try { 
    byte[] example = new String("{}").getBytes("UTF-8"); 
    byte[] avro = converter.convertToAvro(example, mergedSchema); 
    byte[] json = converter.convertToJson(avro, mergedSchema); 
    System.out.println(new String(json)); 
} catch (AvroConversionException e) { 
    e.printStackTrace(); 
} 

:アブロまたはJSON表現への入力JSON。問題は、マージされたスキーマを見ることができないことです。私はそれアブロ不確定性原理:)呼び出す

Exception in thread "main" org.apache.avro.SchemaParseException: Can't redefine: merged schema (generated by AvroStorage).merged 
    at org.apache.avro.Schema$Names.put(Schema.java:1127) 
    at org.apache.avro.Schema$NamedSchema.writeNameRef(Schema.java:561) 
    at org.apache.avro.Schema$RecordSchema.toJson(Schema.java:689) 
    at org.apache.avro.Schema$RecordSchema.fieldsToJson(Schema.java:715) 
    at org.apache.avro.Schema$RecordSchema.toJson(Schema.java:700) 
    at org.apache.avro.Schema.toString(Schema.java:323) 
    at org.apache.avro.Schema.toString(Schema.java:313) 
    at java.lang.String.valueOf(String.java:2982) 
    at java.lang.StringBuilder.append(StringBuilder.java:131) 

:私はシンプルSystem.out.println(mergedSchema)をすれば、私は次の例外を取得します。 avroはマージされたスキーマで動作するようですが、スキーマをJSONにシリアル化しようとすると失敗します。マージは簡単なスキーマで動作するので、avro 1.8.0のバグのように聞こえます。

何が起こっているのか、それを解決する方法が分かっていますか?任意の回避策(例:代替Schemaシリアライザ)を歓迎します。

+0

以前のバージョンのavro(1.7.6)でも発生しているようです。http://mail-archives.apache.org/mod_mbox/avro-user/201406.mbox/%[email protected]。 nabble.com%3E –

答えて

1

私は豚のutilのクラスと同じ問題を発見した...実際に2つのバグがここにあります

  • AVROは貯金utilのクラスが無効なスキーマを生成している無効なスキーマ
  • を使用してGenericDatumWriterを介してデータをシリアル化可能にそれはすべてのマージされたフィールドに同じ名前/名前空間(元の名前を保つのインスタンス)

を使用しているので、これは、より複雑なシナリオのために正常に動作しているhttps://github.com/kite-sdk/kite/blob/master/kite-data/kite-data-core/src/main/java/org/kitesdk/data/spi/SchemaUtil.java#L511

Schema mergedSchema = SchemaUtil.merge(s1, s2); 

あなたの例から、私はうまくいけば、これは他の人を助ける次の出力

{ 
    "type": "record", 
    "name": "event", 
    "namespace": "foo", 
    "fields": [ 
    { 
     "name": "metadata", 
     "type": { 
     "type": "record", 
     "name": "event", 
     "namespace": "foo.metadata", 
     "fields": [ 
      { 
      "name": "onefield", 
      "type": [ 
       "null", 
       "string" 
      ], 
      "default": null 
      }, 
      { 
      "name": "anotherfield", 
      "type": [ 
       "null", 
       "string" 
      ], 
      "default": null 
      } 
     ] 
     }, 
     "default": null 
    } 
    ] 
} 

を取得しています。

+0

Thanks @lake。私はそれを試すことができませんが、それは本当によく見えます。 –

関連する問題