2017-06-17 4 views
0

Actuellement, j'utilise Avro 1.8.0 pour sérialiser/désérialiser des objets, mais en particulier pour l'objet java.util.Map. Pas de problème avec d'autres types d'objets.Problème de sérialisation/désérialisation de carte Avro

Exemple de code ici -

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); 
    } 
} 

Dans la méthode de deserialize Je suis en train d'obtenir le schéma basé sur des données d'entrée, mais Avro est erreur lancer -

`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)` 

Note: A la fin les deux méthodes sera placé dans différentes bibliothèques (avro-serializer/avro-deserializer).

Veuillez suggérer le meilleur moyen d'obtenir un schéma en méthode de désérialisation.

Merci.

Répondre

0

Vous obtenez java.lang.ClassCastException: [B cannot be cast to java.util.Collection parce que vous essayez d'appeler la méthode induce() avec un objet qui est un tableau d'octets mais pas une carte.

Si vous souhaitez sérialiser une carte dans un endroit et désérialiser dans l'autre, vous pouvez utiliser une meilleure façon:

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

Si vous le faites, vous aurez pas besoin de paramètres supplémentaires dans la méthode de desirialize .

En outre, GenericDatumWriter peut être utilisé uniquement avec des enregistrements génériques, vous avez donc besoin d'un ReflectDatumWriter.

Voici un exemple de code avec les changements:

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); 
    } 
} 

En conséquence, vous obtiendrez quelque chose comme ceci:

Deserialized Data : {Key2=Value2, Key1=Value1}