java - Avro Map 序列化/反序列化问题

标签 java json serialization deserialization avro

目前我正在使用 Avro 1.8.0 来序列化/反序列化对象,但面临问题,特别是 java.util.Map 对象。没有遇到其他类型对象的问题。

这里是示例代码-

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

在反序列化方法中,我试图根据输入数据获取架构,但 avro 抛出错误 -

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

请建议在反序列化方法中获取架构的最佳方式。

谢谢。

最佳答案

您得到java.lang.ClassCastException: [B无法转换为java.util.Collection,因为您尝试使用字节对象调用induce()方法数组但不是 Map。

如果您想在一个地方序列化 map 并在另一个地方反序列化它,您可以使用更好的方法:

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

如果这样做,您将不需要在 deserialize 方法中添加任何额外参数。

此外,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}

关于java - Avro Map 序列化/反序列化问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44610042/

相关文章:

javascript - 如何映射 json 并将键名称设置为具有匹配字符串的变量

android - 使用 gson 反序列化 NullPointerException

java - 证书链不包含在签名的 pdf 中

java - 如何将参数传递给 JNLP 启动的 Swing 应用程序?

java - 给定一个 Swing 容器和坐标,我如何找到制造的鼠标事件的源?

arrays - 如何从go lang中的json数组访问键和值

Java 构建器类泛型层次结构 : how to make build() return correct method

json - json HTTP POST的表单内容类型?

c# - 无论如何要计算或获取在 ProgressBar 中显示的序列化时间?

sql-server - 可串行化事务死锁