KafkaAvroDeserializer does not return SpecificRecord but returns GenericRecord

前端 未结 2 1955
Happy的楠姐
Happy的楠姐 2020-12-15 10:17

My KafkaProducer is able to use KafkaAvroSerializer to serialize objects to my topic. However, KafkaConsumer.poll() returns deserializ

2条回答
  •  猫巷女王i
    2020-12-15 11:02

    KafkaAvroDeserializer supports SpecificData

    It's not enabled by default. To enable it:

    properties.put(KafkaAvroDeserializerConfig.SPECIFIC_AVRO_READER_CONFIG, true);
    

    KafkaAvroDeserializer does not support ReflectData

    Confluent's KafkaAvroDeserializer does not know how to deserialize using Avro ReflectData. I had to extend it to support Avro ReflectData:

    /**
     * Extends deserializer to support ReflectData.
     *
     * @param 
     *     value type
     */
    public abstract class ReflectKafkaAvroDeserializer extends KafkaAvroDeserializer {
    
      private Schema readerSchema;
      private DecoderFactory decoderFactory = DecoderFactory.get();
    
      protected ReflectKafkaAvroDeserializer(Class type) {
        readerSchema = ReflectData.get().getSchema(type);
      }
    
      @Override
      protected Object deserialize(
          boolean includeSchemaAndVersion,
          String topic,
          Boolean isKey,
          byte[] payload,
          Schema readerSchemaIgnored) throws SerializationException {
    
        if (payload == null) {
          return null;
        }
    
        int schemaId = -1;
        try {
          ByteBuffer buffer = ByteBuffer.wrap(payload);
          if (buffer.get() != MAGIC_BYTE) {
            throw new SerializationException("Unknown magic byte!");
          }
    
          schemaId = buffer.getInt();
          Schema writerSchema = schemaRegistry.getByID(schemaId);
    
          int start = buffer.position() + buffer.arrayOffset();
          int length = buffer.limit() - 1 - idSize;
          DatumReader reader = new ReflectDatumReader(writerSchema, readerSchema);
          BinaryDecoder decoder = decoderFactory.binaryDecoder(buffer.array(), start, length, null);
          return reader.read(null, decoder);
        } catch (IOException e) {
          throw new SerializationException("Error deserializing Avro message for id " + schemaId, e);
        } catch (RestClientException e) {
          throw new SerializationException("Error retrieving Avro schema for id " + schemaId, e);
        }
      }
    }
    
    
    

    Define a custom deserializer class which deserializes to MyBean:

    public class MyBeanDeserializer extends ReflectKafkaAvroDeserializer {
      public MyBeanDeserializer() {
        super(MyBean.class);
      }
    }
    

    Configure KafkaConsumer to use the custom deserializer class:

    properties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, MyBeanDeserializer.class);
    

    提交回复
    热议问题