Java Jackson序列化和反序列化Map<;字符串,字节[]>;
使用Jackson对映射进行序列化和反序列化的正确方法是什么 我一直在这样做:Java Jackson序列化和反序列化Map<;字符串,字节[]>;,java,json,jackson,Java,Json,Jackson,使用Jackson对映射进行序列化和反序列化的正确方法是什么 我一直在这样做: byte[] toPostgres = OBJECT_MAPPER.writeValueAsBytes(context); 我创建了一个地图: 然后从博士后那里读到: Map<String, byte[]> fromPostgres = OBJECT_MAPPER.readValue(toPostgres, Map.class) 我得到以下错误: 感兴趣的部分: com.fasterxml.jacks
byte[] toPostgres = OBJECT_MAPPER.writeValueAsBytes(context);
我创建了一个地图
:
然后从博士后那里读到:
Map<String, byte[]> fromPostgres = OBJECT_MAPPER.readValue(toPostgres, Map.class)
我得到以下错误:
感兴趣的部分:
com.fasterxml.jackson.databind.JsonMappingException: class java.lang.String cannot be cast to class [B (java.lang.String and [B are in module java.base of loader 'bootstrap') (through reference chain: com.amce.MyMessage["context"]->java.util.LinkedHashMap["outer-key"])
"exception":"java.lang.ClassCastException: class java.lang.String cannot be cast to class [B (java.lang.String and [B are in module java.base of loader 'bootstrap')
at com.fasterxml.jackson.databind.ser.std.ByteArraySerializer.serialize(ByteArraySerializer.java:30)
at com.fasterxml.jackson.databind.ser.std.MapSerializer.serializeFieldsUsing(MapSerializer.java:817)
... 23 common frames omitted
Wrapped by: com.fasterxml.jackson.databind.JsonMappingException: class java.lang.String cannot be cast to class [B (java.lang.String and [B are in module java.base of loader 'bootstrap') (through reference chain: com.amce.MyMessage[\"context\"]->java.util.LinkedHashMap[\"outer-key\"])
at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:397)
at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:356)
at com.fasterxml.jackson.databind.ser.std.StdSerializer.wrapAndThrow(StdSerializer.java:316)
at com.fasterxml.jackson.databind.ser.std.MapSerializer.serializeFieldsUsing(MapSerializer.java:822)
at com.fasterxml.jackson.databind.ser.std.MapSerializer.serialize(MapSerializer.java:641)
at com.fasterxml.jackson.databind.ser.std.MapSerializer.serialize(MapSerializer.java:33)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:727)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:722)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:166)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider._serialize(DefaultSerializerProvider.java:480)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:319)
at com.fasterxml.jackson.databind.ObjectMapper._configAndWriteValue(ObjectMapper.java:4110)
at com.fasterxml.jackson.databind.ObjectMapper.writeValueAsBytes(ObjectMapper.java:3437)
at
完全错误:
com.fasterxml.jackson.databind.JsonMappingException: class java.lang.String cannot be cast to class [B (java.lang.String and [B are in module java.base of loader 'bootstrap') (through reference chain: com.amce.MyMessage["context"]->java.util.LinkedHashMap["outer-key"])
"exception":"java.lang.ClassCastException: class java.lang.String cannot be cast to class [B (java.lang.String and [B are in module java.base of loader 'bootstrap')
at com.fasterxml.jackson.databind.ser.std.ByteArraySerializer.serialize(ByteArraySerializer.java:30)
at com.fasterxml.jackson.databind.ser.std.MapSerializer.serializeFieldsUsing(MapSerializer.java:817)
... 23 common frames omitted
Wrapped by: com.fasterxml.jackson.databind.JsonMappingException: class java.lang.String cannot be cast to class [B (java.lang.String and [B are in module java.base of loader 'bootstrap') (through reference chain: com.amce.MyMessage[\"context\"]->java.util.LinkedHashMap[\"outer-key\"])
at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:397)
at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:356)
at com.fasterxml.jackson.databind.ser.std.StdSerializer.wrapAndThrow(StdSerializer.java:316)
at com.fasterxml.jackson.databind.ser.std.MapSerializer.serializeFieldsUsing(MapSerializer.java:822)
at com.fasterxml.jackson.databind.ser.std.MapSerializer.serialize(MapSerializer.java:641)
at com.fasterxml.jackson.databind.ser.std.MapSerializer.serialize(MapSerializer.java:33)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:727)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:722)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:166)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider._serialize(DefaultSerializerProvider.java:480)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:319)
at com.fasterxml.jackson.databind.ObjectMapper._configAndWriteValue(ObjectMapper.java:4110)
at com.fasterxml.jackson.databind.ObjectMapper.writeValueAsBytes(ObjectMapper.java:3437)
at
我在这篇帖子上找到了答案:
而不是:
Map<String, byte[]> fromPostgres = OBJECT_MAPPER.readValue(toPostgres, Map.class)
byte[] toPostgres = OBJECT_MAPPER.writeValueAsBytes(context);
Map fromPostgres=OBJECT\u MAPPER.readValue(toPostgres,Map.class)
使用:
TypeReference typeRef
=新类型引用()
{
};
Map fromPostgres=OBJECT\u MAPPER.readValue(toPostgres,typeRef);
我只是想确定这是序列化和反序列化
映射的正确方法,其中字节[]
数组可以是任何东西,例如另一个类等?可能,当您从泛型类型保存数据时,您也会使用类型感知写入
而不是:
Map<String, byte[]> fromPostgres = OBJECT_MAPPER.readValue(toPostgres, Map.class)
byte[] toPostgres = OBJECT_MAPPER.writeValueAsBytes(context);
使用:
其中,typeRef与数据恢复期间的值相同。Jackson的ObjectMapper
将数据转换为JSON或从JSON转换为JSON。JSON只有五种数据类型(字符串、数字、布尔值、对象和数组),但Java显然还有更多。Jackson序列化数据时类型信息丢失,然后在反序列化数据时必须猜测类型信息
Jackson将示例上下文内容序列化为:
{“a-context-key”:“a-context-value”}
由于值和键都是原始字符串,而JSON对象是Java映射的自然等价物,所以这很好。当被要求将值写入字节时,Jackson认为JSON的UTF-8编码是合适的
JSON没有字节数组的表示形式,因此Jackson使用Base-64对数据进行编码,将其转换为JSON字符串。因此,上下文
如下所示:
abstract static class MixInUnicodeBlock {
@JsonCreator
public static UnicodeBlock forName(String name) {
return UnicodeBlock.forName(name);
}
@JsonValue
public abstract String toString();
}
public void example() {
ObjectMapper OBJECT_MAPPER = new ObjectMapper();
OBJECT_MAPPER.addMixIn(UnicodeBlock.class,MixInUnicodeBlock.class);
System.out.println(OBJECT_MAPPER.writeValueAsString(UnicodeBlock.GREEK));
System.out.println(OBJECT_MAPPER.readValue("\"GREEK\"",UnicodeBlock.class));
}
{“外键”:“eyjhlwnvbnlehqta2v5ijoiys1jb250zxh0lxzhbhvlin0=“}
该值曾经是字节[]
的事实将丢失
当Jackson被要求通过以下方式反序列化:
Map<String, byte[]> fromPostgres = OBJECT_MAPPER.readValue(toPostgres, Map.class)
允许在编译时指定键和值的类型,方法是生成一个匿名类,其嵌入的泛型信息与映射的键和值类型匹配
也可以在运行时使用Jackson的类型工厂完成:
Class<?> keyType = String.class;
Class<?> valueType = byte[].class;
JavaType mapType = OBJECT_MAPPER.getTypeFactory()
.constructMapType(
Map.class,
keyType,
valueType);
Map<String, byte[]> fromPostgres = OBJECT_MAPPER.readValue(toPostgres, mapType);
将失败,即使Jackson可以仅使用其名称成功地序列化和反序列化该类。在这种情况下,可以通过使用“混音”来告诉Jackson该怎么做,如下所示:
abstract static class MixInUnicodeBlock {
@JsonCreator
public static UnicodeBlock forName(String name) {
return UnicodeBlock.forName(name);
}
@JsonValue
public abstract String toString();
}
public void example() {
ObjectMapper OBJECT_MAPPER = new ObjectMapper();
OBJECT_MAPPER.addMixIn(UnicodeBlock.class,MixInUnicodeBlock.class);
System.out.println(OBJECT_MAPPER.writeValueAsString(UnicodeBlock.GREEK));
System.out.println(OBJECT_MAPPER.readValue("\"GREEK\"",UnicodeBlock.class));
}
总之,为了成功地序列化Map
:
- 如果这是根值,则需要提供缺少的通用信息。
- 您可以在编译时使用
TypeReference
来存储通用信息
- 您可以使用
TypeFactory
创建JavaType
实例,从而允许在运行时指定它
- 如果映射是类的属性,则将保留泛型信息,并且可能不需要进一步指定
- 一个类可能需要直接注释,或者通过一个mix-in来成功处理
- 为了精确控制序列化和反序列化,有时需要自定义序列化程序或反序列化程序
您是否尝试过将字节[]转换为Base64字符串,并使用它?
abstract static class MixInUnicodeBlock {
@JsonCreator
public static UnicodeBlock forName(String name) {
return UnicodeBlock.forName(name);
}
@JsonValue
public abstract String toString();
}
public void example() {
ObjectMapper OBJECT_MAPPER = new ObjectMapper();
OBJECT_MAPPER.addMixIn(UnicodeBlock.class,MixInUnicodeBlock.class);
System.out.println(OBJECT_MAPPER.writeValueAsString(UnicodeBlock.GREEK));
System.out.println(OBJECT_MAPPER.readValue("\"GREEK\"",UnicodeBlock.class));
}