簡體   English   中英

Avro和Java:字符串的反序列化映射不“等於”原始映射

[英]Avro and java: deserialized map of string doesn't “equals” original map

我正在用包含字符串和映射的簡單記錄測試Java的Avro。 這是我的架構:

{
  "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}>

如您所見,兩個映射看起來相同,但是測試失敗。 JUnit在幕后調用了“等於”方法,該方法應返回true。 順便說一句,如果您想知道什么是亂碼,我通常使用隨機生成的數據來創建測試用例,因此這就是它的來歷。

難道我做錯了什么? 我不知道字符串串行化/反序列化有什么用嗎? 我在網上搜索沒有成功。

想法?

謝謝

Giodude

我弄清楚了什么是“漁獲”。 我正在將包含java.lang.String的映射與包含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

我猜這是可以預期的,因為Avro總是將字符串轉換為其本地的Utf8類型。 我以為它會照原樣復制我的地圖,但事實並非如此。 映射到Map的類型成功是很奇怪的,我不清楚這是如何發生的。

是的,Avro map從1.5開始就使用org.apache.avro.util.Utf8作為默認鍵,並且可以更改為String。 有關更多詳細信息,請參閱: https : //issues.apache.org/jira/browse/AVRO-803Apache Avro:地圖使用CharSequence作為鍵

暫無
暫無

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

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