Java Kafka Avro序列化程序和反序列化程序

Java Kafka Avro序列化程序和反序列化程序,java,apache-kafka,avro,Java,Apache Kafka,Avro,我想实现基于Avro的通用Kafka序列化器/反序列化器。它应该是通用的,不使用对象。要求使用像GenericRecord.get(“myValue”)这样的东西 这是我的序列化程序的代码 import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.Map; import org.apache.avro.generic.GenericDatumWriter; import org.apac

我想实现基于Avro的通用Kafka序列化器/反序列化器。它应该是通用的,不使用对象。要求使用像GenericRecord.get(“myValue”)这样的东西

这是我的序列化程序的代码

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Map;

import org.apache.avro.generic.GenericDatumWriter;
import org.apache.avro.generic.GenericRecord;
import org.apache.avro.io.BinaryEncoder;
import org.apache.avro.io.DatumWriter;
import org.apache.avro.io.EncoderFactory;
import org.apache.kafka.common.errors.SerializationException;
import org.apache.kafka.common.serialization.Serializer;

public class AvroSerializer implements Serializer<GenericRecord> {

  public void configure(Map<String, ?> configs, boolean isKey) {

  }

  public byte[] serialize(String topic, GenericRecord data) {
    try {
      byte[] result = null;

      if (data != null) {

        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        BinaryEncoder binaryEncoder =
            EncoderFactory.get().binaryEncoder(byteArrayOutputStream, null);

        DatumWriter<GenericRecord> datumWriter = new GenericDatumWriter<GenericRecord>(data.getSchema());
        datumWriter.write(data, binaryEncoder);

        binaryEncoder.flush();
        byteArrayOutputStream.close();

        result = byteArrayOutputStream.toByteArray();
      }
      return result;
    } catch (IOException ex) {
      throw new SerializationException(
          "Can't serialize data='" + data + "' for topic='" + topic + "'", ex);
    }
  }

  public void close() {

  }

}
import java.util.Arrays;
import java.util.Map;

import org.apache.avro.generic.GenericDatumReader;
import org.apache.avro.generic.GenericRecord;
import org.apache.avro.io.DatumReader;
import org.apache.avro.io.Decoder;
import org.apache.avro.io.DecoderFactory;
import org.apache.kafka.common.errors.SerializationException;
import org.apache.kafka.common.serialization.Deserializer;

public class AvroDeserializer implements Deserializer<GenericRecord> {

  @Override
  public void close() {

  }

  @Override
  public void configure(Map<String, ?> configs, boolean isKey) {

  }

  @Override
  public GenericRecord deserialize(String topic, byte[] data) {
    try {
      GenericRecord result = null;

      if (data != null) {
        DatumReader<GenericRecord> reader = new GenericDatumReader<GenericRecord>();
        Decoder decoder = DecoderFactory.get().binaryDecoder(data, null);
        result = reader.read(null, decoder);
      }
      return result;
     } catch (Exception ex) {
      throw new SerializationException(
      "Can't deserialize data '" + Arrays.toString(data) + "' from topic '" + topic + "'", ex);
    }
  }

}
import java.io.ByteArrayOutputStream;
导入java.io.IOException;
导入java.util.Map;
导入org.apache.avro.generic.GenericDatumWriter;
导入org.apache.avro.generic.GenericRecord;
导入org.apache.avro.io.BinaryEncoder;
导入org.apache.avro.io.DatumWriter;
导入org.apache.avro.io.EncoderFactory;
导入org.apache.kafka.common.errors.SerializationException;
导入org.apache.kafka.common.serialization.Serializer;
公共类AvroSerializer实现序列化程序{
公共无效配置(映射配置、布尔isKey){
}
公共字节[]序列化(字符串主题,GenericRecord数据){
试一试{
字节[]结果=空;
如果(数据!=null){
ByteArrayOutputStream ByteArrayOutputStream=新建ByteArrayOutputStream();
二进制编码器二进制编码器=
EncoderFactory.get().binaryEncoder(byteArrayOutputStream,null);
DatumWriter DatumWriter=新的GenericDatumWriter(data.getSchema());
写入(数据,二进制编码器);
binaryEncoder.flush();
byteArrayOutputStream.close();
结果=byteArrayOutputStream.toByteArray();
}
返回结果;
}捕获(IOEX异常){
抛出新的序列化异常(
对于主题='“+topic+”,ex),无法序列化数据='“+data+”;
}
}
公众假期结束(){
}
}
这是反序列化程序

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Map;

import org.apache.avro.generic.GenericDatumWriter;
import org.apache.avro.generic.GenericRecord;
import org.apache.avro.io.BinaryEncoder;
import org.apache.avro.io.DatumWriter;
import org.apache.avro.io.EncoderFactory;
import org.apache.kafka.common.errors.SerializationException;
import org.apache.kafka.common.serialization.Serializer;

public class AvroSerializer implements Serializer<GenericRecord> {

  public void configure(Map<String, ?> configs, boolean isKey) {

  }

  public byte[] serialize(String topic, GenericRecord data) {
    try {
      byte[] result = null;

      if (data != null) {

        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        BinaryEncoder binaryEncoder =
            EncoderFactory.get().binaryEncoder(byteArrayOutputStream, null);

        DatumWriter<GenericRecord> datumWriter = new GenericDatumWriter<GenericRecord>(data.getSchema());
        datumWriter.write(data, binaryEncoder);

        binaryEncoder.flush();
        byteArrayOutputStream.close();

        result = byteArrayOutputStream.toByteArray();
      }
      return result;
    } catch (IOException ex) {
      throw new SerializationException(
          "Can't serialize data='" + data + "' for topic='" + topic + "'", ex);
    }
  }

  public void close() {

  }

}
import java.util.Arrays;
import java.util.Map;

import org.apache.avro.generic.GenericDatumReader;
import org.apache.avro.generic.GenericRecord;
import org.apache.avro.io.DatumReader;
import org.apache.avro.io.Decoder;
import org.apache.avro.io.DecoderFactory;
import org.apache.kafka.common.errors.SerializationException;
import org.apache.kafka.common.serialization.Deserializer;

public class AvroDeserializer implements Deserializer<GenericRecord> {

  @Override
  public void close() {

  }

  @Override
  public void configure(Map<String, ?> configs, boolean isKey) {

  }

  @Override
  public GenericRecord deserialize(String topic, byte[] data) {
    try {
      GenericRecord result = null;

      if (data != null) {
        DatumReader<GenericRecord> reader = new GenericDatumReader<GenericRecord>();
        Decoder decoder = DecoderFactory.get().binaryDecoder(data, null);
        result = reader.read(null, decoder);
      }
      return result;
     } catch (Exception ex) {
      throw new SerializationException(
      "Can't deserialize data '" + Arrays.toString(data) + "' from topic '" + topic + "'", ex);
    }
  }

}
导入java.util.array;
导入java.util.Map;
导入org.apache.avro.generic.GenericDatumReader;
导入org.apache.avro.generic.GenericRecord;
导入org.apache.avro.io.DatumReader;
导入org.apache.avro.io.Decoder;
导入org.apache.avro.io.DecoderFactory;
导入org.apache.kafka.common.errors.SerializationException;
导入org.apache.kafka.common.serialization.Deserializer;
公共类AvroDeserializer实现反序列化器{
@凌驾
公众假期结束(){
}
@凌驾
公共无效配置(映射配置、布尔isKey){
}
@凌驾
公共GenericRecord反序列化(字符串主题,字节[]数据){
试一试{
GenericRecord结果=空;
如果(数据!=null){
DatumReader=新的GenericDatumReader();
Decoder Decoder=DecoderFactory.get().binaryDecoder(数据,null);
结果=reader.read(空,解码器);
}
返回结果;
}捕获(例外情况除外){
抛出新的序列化异常(
“无法反序列化数据”“+数组。toString(数据)+”“来自主题”“+主题+”,ex);
}
}
}
不幸的是,当Kafka消息被反序列化时,我得到了一个SerializationException

Caused by: org.apache.kafka.common.errors.SerializationException: Error deserializing key/value for partition my.topic-0 at offset 7
Caused by: org.apache.kafka.common.errors.SerializationException: Can't deserialize data '[72, -31, 122, 20, -82, 7, 89, 64]' from topic 'my.topic'
Caused by: java.lang.NullPointerException: writer cannot be null!
at org.apache.avro.io.ResolvingDecoder.resolve(ResolvingDecoder.java:80)
at org.apache.avro.io.ResolvingDecoder.<init>(ResolvingDecoder.java:49)
at org.apache.avro.io.DecoderFactory.resolvingDecoder(DecoderFactory.java:307)
at org.apache.avro.generic.GenericDatumReader.getResolver(GenericDatumReader.java:128)
at org.apache.avro.generic.GenericDatumReader.read(GenericDatumReader.java:143)
at com.mydomain.serialization.AvroDeserializer.deserialize(AvroDeserializer.java:34)
at com.mydomain.serialization.AvroDeserializer.deserialize(AvroDeserializer.java:1) 
原因:org.apache.kafka.common.errors.SerializationException:在偏移量7处反序列化分区my.topic-0的键/值时出错
原因:org.apache.kafka.common.errors.SerializationException:无法反序列化主题“my.topic”中的数据“[72,-31,122,20,-82,7,89,64]”
原因:java.lang.NullPointerException:writer不能为null!
位于org.apache.avro.io.ResolvingDecoder.resolve(ResolvingDecoder.java:80)
位于org.apache.avro.io.ResolvingDecoder(ResolvingDecoder.java:49)
位于org.apache.avro.io.DecoderFactory.resolvingDecoder(DecoderFactory.java:307)
位于org.apache.avro.generic.GenericDatumReader.getResolver(GenericDatumReader.java:128)
位于org.apache.avro.generic.GenericDatumReader.read(GenericDatumReader.java:143)
在com.mydomain.serialization.AvroDeserializer.deserialize上(AvroDeserializer.java:34)
在com.mydomain.serialization.AvroDeserializer.deserialize(AvroDeserializer.java:1)上

您可以选择使用模式注册表吗?如果你使用SR Kafka Avro Ser/Des是现成的。你使用SchemaRegistry进行模式注册吗?不,我没有尝试schema registry是的。看,那里还有一个博客没有使用注册表