2

文字列とマップで構成される単純なレコードを使用して、Avro for Java をテストしています。ここに私のスキーマがあります:

{
  "type":"record",
  "name":"TableRecord",
  "fields":[
    {"name":"ActionCode","type":"string"},
    {
      "name":"Fields",
      "type":{"type":"map","values":["string","long","double","null"]}
    }
  ]
}

そして、これは失敗する非常に単純なテスト ケースです。

@Test
public void testSingleMapSerialization() throws IOException {
    final String schemaStr; // see above

    // create some data
    Map<String, Object> originalMap = new Hashtable<>();
    originalMap.put("Ric", "sZwmXAdYKv");
    originalMap.put("QuoteId", 4342740204922826921L);
    originalMap.put("CompanyName", "8PKQ9va3nW8pRWb4SjPF2DvdQDBmlZ");
    originalMap.put("Category", "AvrIfd");

    // serialize data
    Schema.Parser parser = new Schema.Parser();
    Schema schema = parser.parse(schemaStr);
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    DatumWriter<GenericRecord> writer = new GenericDatumWriter<>(schema);
    Encoder encoder = EncoderFactory.get().binaryEncoder(out, null);
    GenericRecord datum = new GenericData.Record(schema);
    datum.put("ActionCode", "R");
    datum.put("Map", originalMap);
    writer.write(datum, encoder);
    encoder.flush();
    out.flush();

    // deserialize data
    DatumReader<GenericRecord> reader = new GenericDatumReader<>(schema);
    Decoder decoder = DecoderFactory.get().binaryDecoder(out.toByteArray(), null);
    datum = new GenericData.Record(schema);
    Map<String, Object> deserializedMap = (Map<String, Object>) reader.read(datum, decoder).get("Map");
    System.out.println(originalMap);
    System.out.println(deserializedMap);
    Assert.assertEquals("Maps data don't match", originalMap, deserializedMap);
}

テストの出力は次のとおりです。

{CompanyName=8PKQ9va3nW8pRWb4SjPF2DvdQDBmlZ, Ric=sZwmXAdYKv, Category=AvrIfd, QuoteId=4342740204922826921}
{QuoteId=4342740204922826921, Category=AvrIfd, CompanyName=8PKQ9va3nW8pRWb4SjPF2DvdQDBmlZ, Ric=sZwmXAdYKv}

java.lang.AssertionError: Maps data don't match expected:<{CompanyName=8PKQ9va3nW8pRWb4SjPF2DvdQDBmlZ, Ric=sZwmXAdYKv, Category=AvrIfd, QuoteId=4342740204922826921}> but was:<{QuoteId=4342740204922826921, Category=AvrIfd, CompanyName=8PKQ9va3nW8pRWb4SjPF2DvdQDBmlZ, Ric=sZwmXAdYKv}>

ご覧のとおり、2 つのマップは同じように見えますが、テストは失敗します。JUnit は内部で「equals」メソッドを呼び出し、true を返す必要があります。ところで、意味不明なことを知りたい場合は、通常、ランダムに生成されたデータを使用してテスト ケースを作成します。

私は何か間違ったことをしていますか?私が気付いていない文字列のシリアライゼーション/デシリアライゼーションのキャッチはありますか? オンラインで検索しましたが、成功しませんでした。

アイデア?

ありがとう

ジオデュード

4

2 に答える 2

3

私は「キャッチ」が何であるかを理解しました。java.lang.Strings を含むマップと を含むマップを比較していましたorg.apache.avro.util.Utf8。文字列で使用すると、Utf8 の equals メソッドが機能しないことが判明しました。テストケースに次を追加することでこれを実現しました。

for (Object o : deserializedMap.values())
  System.out.println(o.getClass());
for (Object o : deserializedMap.keySet())
  System.out.println(o.getClass());

以下を出力します。

class java.lang.Long
class org.apache.avro.util.Utf8
class org.apache.avro.util.Utf8
class org.apache.avro.util.Utf8
class org.apache.avro.util.Utf8
class org.apache.avro.util.Utf8
class org.apache.avro.util.Utf8
class org.apache.avro.util.Utf8

Utf8Avro は常に文字列をそのネイティブ型に変換するため、これは当然のことだったと思います。マップをそのまま再現すると思っていたのですが、そうではありません。Map への型キャストが成功したのは奇妙です。それがどのように起こったのかは明確ではありません。

于 2013-03-28T20:43:09.337 に答える
1

はい、Avro マップは org.apache.avro.util.Utf8 を 1.5 以降のデフォルト キーとして使用しており、文字列に変更できます。詳細については、https: //issues.apache.org/jira/browse/AVRO-803またはApache Avro を参照してください。マップは CharSequence をキーとして使用します

于 2014-05-19T07:16:13.960 に答える