2017-06-17 17 views
0

現在、私はAvro 1.8.0を使用してオブジェクトをシリアル化/逆シリアル化しますが、特にjava.util.Mapオブジェクトの場合は問題に直面しています。他のタイプのオブジェクトで問題に直面していません。ここAvroマップのシリアル化/逆シリアル化の問題

サンプルコード - デシリアライズ方法で

class AvroUtils { 

    public byte[] serialize(Object payload) { 
     final ByteArrayOutputStream out = new ByteArrayOutputStream(); 
     Schema schema = new ReflectDatumWriter().getData().induce(payload); //---> getting proper map schema as {"type":"map","values":"string"} 
     JsonEncoder jsonEncoder = EncoderFactory.get().jsonEncoder(schema, out); 
     final GenericDatumWriter<Object> writer = new GenericDatumWriter(schema); 
     writer.write(payload, jsonEncoder); 
     jsonEncoder.flush(); 
     return out.toByteArray(); 
    } 

    public <R> R deserialize(Object o, Class<R> aClass) { 
     Schema schema = new ReflectDatumWriter().getData().induce(o); //------> getting error - unable to get schema 
     final ByteArrayInputStream bin = new ByteArrayInputStream((byte[]) o); 
     JsonDecoder jsonDecoder = DecoderFactory.get().jsonDecoder(schema, bin); 
     final GenericDatumReader<R> reader = new GenericDatumReader<>(schema); 
     return reader.read(null, jsonDecoder); 
    } 

    public static void main(String[] args) { 
     Map<String, Object> map = new HashMap<String, Object>(); 
     map.put("Key1", "Value1"); 
     map.put("Key2", "Value2"); 

     // Serialization 
     byte[] result = this.serialize(map); 
     System.out.println("Serialized Data : " + new String(mapDes, "UTF-8")); 

     // Deserialization 
     Map<String, Object> mapDes = (Map<String, Object>) this.deserialize(result, Map.class); 
     System.out.println("Deserialized Data : " + mapDes); 
    } 
} 

私は、入力データが、アブロに基づいて、スキーマを取得しようとしていますがエラーを投げている -

`Exception in thread "main" java.lang.ClassCastException: [B cannot be cast to java.util.Collection 
at org.apache.avro.reflect.ReflectData.getArrayAsCollection(ReflectData.java:196) 
at org.apache.avro.generic.GenericData.induce(GenericData.java:612)` 

注:最後には両方の方法を別のライブラリ(avro-serializer/avro-deserializer)に配置されます。

デシリアライズメソッドでスキーマを取得する最善の方法を提案してください。

ありがとうございました。

答えて

0

induce()メソッドを呼び出すと、オブジェクトがバイト配列であるがマップではないため、java.lang.ClassCastException: [B cannot be cast to java.util.Collectionが返されます。

使用すると、1つの場所でマップをシリアル化し、他でそれをデシリアライズしたい場合は、あなたがより良い方法を使用することができます。

Schema schema = Schema.createMap(Schema.create(Schema.Type.STRING)); 

その場合、あなたはdesirializeの方法のいずれかの追加のパラメータを必要としません。

また、GenericDatumWriterは汎用レコードでのみ使用できるため、ReflectDatumWriterが必要です。ここで

が変更にあなたのコードの例です:

public class AvroUtils { 

    public static byte[] serialize(Object payload) throws IOException { 
     final ByteArrayOutputStream out = new ByteArrayOutputStream(); 
     Schema schema = Schema.createMap(Schema.create(Schema.Type.STRING)); //---> getting proper map schema as {"type":"map","values":"string"} 
     JsonEncoder jsonEncoder = EncoderFactory.get().jsonEncoder(schema, out); 
     final DatumWriter<Object> writer = new ReflectDatumWriter<>(schema); 
     writer.write(payload, jsonEncoder); 
     jsonEncoder.flush(); 
     return out.toByteArray(); 
    } 

    public static <R> R deserialize(Object o) throws IOException { 
     Schema schema = Schema.createMap(Schema.create(Schema.Type.STRING)); 
     JsonDecoder jsonDecoder = DecoderFactory.get().jsonDecoder(schema, new ByteArrayInputStream((byte[]) o)); 
     final DatumReader<R> reader = new ReflectDatumReader<>(schema); 
     return reader.read(null, jsonDecoder); 
    } 

    public static void main(String[] args) throws IOException { 
     Map<String, Object> map = new HashMap<>(); 
     map.put("Key1", "Value1"); 
     map.put("Key2", "Value2"); 

     // Serialization 
     byte[] result = serialize(map); 

     // Deserialization 
     Map<String, Object> mapDes = deserialize(result); 
     System.out.println("Deserialized Data : " + mapDes); 
    } 
} 

その結果、あなたはこのような何か買ってあげる:

Deserialized Data : {Key2=Value2, Key1=Value1} 
関連する問題