使用 Jackson 反序列化 Java 个数组
Deserializing Java arrays with Jackson
我正在尝试使用 Jackson 作为通用序列化引擎而不是 Java 序列化。
通过以下方式初始化映射器:
objectMapper = new ObjectMapper();
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
所有类型信息都存储在 JSON 中,因此我可以通过以下方式写入和读取我的所有对象:
objectMapper.readValue(json, Object.class)
我在尝试序列化然后反序列化 java 数组时遇到问题。
由于 Jackson 没有将数组类型存储到 JSON 中,因此它在反序列化阶段稍后会失败。在以下代码中:
String [] strings = {"A", "B", "C"};
try {
String json = objectMapper.writeValueAsString(strings);
String [] stringsBack = (String [])objectMapper.readValue(json, Object.class);
if (!strings.equals(stringsBack)) {
System.err.println("ERROR, stringsBack not the same!!!\n\n");
}
} catch (IOException e) {
e.printStackTrace();
}
json 将设置为“["A","B","C"]”但是在反序列化时我得到以下异常:
Exception in thread "main" java.lang.IllegalArgumentException: Invalid type id 'A' (for id type 'Id.class'): no such class found
at com.fasterxml.jackson.databind.jsontype.impl.ClassNameIdResolver._typeFromId(ClassNameIdResolver.java:66)
at com.fasterxml.jackson.databind.jsontype.impl.ClassNameIdResolver.typeFromId(ClassNameIdResolver.java:48)
at com.fasterxml.jackson.databind.jsontype.impl.TypeDeserializerBase._findDeserializer(TypeDeserializerBase.java:157)
at com.fasterxml.jackson.databind.jsontype.impl.AsArrayTypeDeserializer._deserialize(AsArrayTypeDeserializer.java:94)
at com.fasterxml.jackson.databind.jsontype.impl.AsArrayTypeDeserializer.deserializeTypedFromAny(AsArrayTypeDeserializer.java:68)
at com.fasterxml.jackson.databind.deser.std.UntypedObjectDeserializer$Vanilla.deserializeWithType(UntypedObjectDeserializer.java:494)
at com.fasterxml.jackson.databind.deser.impl.TypeWrappedDeserializer.deserialize(TypeWrappedDeserializer.java:42)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3560)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2576)
at Main.run(Main.java:86)
有没有办法指示 Jackson 将 java 数组类型信息也存储到 JSON 中?
我的序列化引擎是通用的,并且事先不知道它将从 JSON 字符串中读取的类型。
我目前找到的最佳解决方案是在序列化之前检查对象是否为数组 (Class.isArray),然后进行序列化:
TypeReference ref = new TypeReference<List[]>() { };
String json = objectMapper.writerFor(ref).writeValueAsString(strings);
这会将数组类型添加到 JSON 中并允许读取它。
正确的方法是:
String[] strings = { "A", "B", "C" };
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(strings);
List<String> data = mapper.readValue(json,
mapper.getTypeFactory().constructCollectionType(List.class, String.class));
for (String string : data) {
System.out.println(string);
}
代码存在多个问题。
1) 首先让我们看看为什么会出现异常
Exception in thread "main" java.lang.IllegalArgumentException: Invalid type id 'A' (for id type 'Id.class'): no such class found
上面的错误表明它没有找到一些 Class 并将 A 称为无效类型 ID 'A',这似乎是 Json 中的一个问题。
问题是因为行
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
这为所有非最终类型启用了默认类型。默认类型打印 Object 的类型和 Object 的实际值,因此可以反序列化为相同的类型。声明它 NON_FINAL 不会添加 "natural" 类型,例如 String.
和
String [] stringsBack = (String [])objectMapper.readValue(json, Object.class);
现在反序列化 Json ["A"、"B"、"C"] 时,反序列化器不知道 json 要转换的对象也将 A 作为 Class 类型并试图找到它没有得到的 class。
2) 评论第一行可能会给出 ClassCastException 因为
objectMapper.readValue(json, Object.class);
会 return 一个 ArrayList 的对象,它不能转换为 String[]。
3) !strings.equals(stringsBack)
将始终 return 为真,因为 strings 和 stringsBack 都是 String[] 的不同对象。
更正以下代码中的所有内容即可
ObjectMapper objectMapper = new ObjectMapper();
//You can remove the below line if Default Typing is not Required.
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
String[] strings = { "A", "B", "C" };
try
{
String json = objectMapper.writeValueAsString(strings);
System.out.println(json);
String[] stringsBack = (String[]) objectMapper.readValue(json, new TypeReference<String[]>()
{});
if (!Arrays.equals(strings, stringsBack))
{
System.err.println("ERROR, stringsBack not the same!!!\n\n");
}
}
catch (IOException e)
{
e.printStackTrace();
}
我正在尝试使用 Jackson 作为通用序列化引擎而不是 Java 序列化。 通过以下方式初始化映射器:
objectMapper = new ObjectMapper();
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
所有类型信息都存储在 JSON 中,因此我可以通过以下方式写入和读取我的所有对象:
objectMapper.readValue(json, Object.class)
我在尝试序列化然后反序列化 java 数组时遇到问题。 由于 Jackson 没有将数组类型存储到 JSON 中,因此它在反序列化阶段稍后会失败。在以下代码中:
String [] strings = {"A", "B", "C"};
try {
String json = objectMapper.writeValueAsString(strings);
String [] stringsBack = (String [])objectMapper.readValue(json, Object.class);
if (!strings.equals(stringsBack)) {
System.err.println("ERROR, stringsBack not the same!!!\n\n");
}
} catch (IOException e) {
e.printStackTrace();
}
json 将设置为“["A","B","C"]”但是在反序列化时我得到以下异常:
Exception in thread "main" java.lang.IllegalArgumentException: Invalid type id 'A' (for id type 'Id.class'): no such class found
at com.fasterxml.jackson.databind.jsontype.impl.ClassNameIdResolver._typeFromId(ClassNameIdResolver.java:66)
at com.fasterxml.jackson.databind.jsontype.impl.ClassNameIdResolver.typeFromId(ClassNameIdResolver.java:48)
at com.fasterxml.jackson.databind.jsontype.impl.TypeDeserializerBase._findDeserializer(TypeDeserializerBase.java:157)
at com.fasterxml.jackson.databind.jsontype.impl.AsArrayTypeDeserializer._deserialize(AsArrayTypeDeserializer.java:94)
at com.fasterxml.jackson.databind.jsontype.impl.AsArrayTypeDeserializer.deserializeTypedFromAny(AsArrayTypeDeserializer.java:68)
at com.fasterxml.jackson.databind.deser.std.UntypedObjectDeserializer$Vanilla.deserializeWithType(UntypedObjectDeserializer.java:494)
at com.fasterxml.jackson.databind.deser.impl.TypeWrappedDeserializer.deserialize(TypeWrappedDeserializer.java:42)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3560)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2576)
at Main.run(Main.java:86)
有没有办法指示 Jackson 将 java 数组类型信息也存储到 JSON 中? 我的序列化引擎是通用的,并且事先不知道它将从 JSON 字符串中读取的类型。
我目前找到的最佳解决方案是在序列化之前检查对象是否为数组 (Class.isArray),然后进行序列化:
TypeReference ref = new TypeReference<List[]>() { };
String json = objectMapper.writerFor(ref).writeValueAsString(strings);
这会将数组类型添加到 JSON 中并允许读取它。
正确的方法是:
String[] strings = { "A", "B", "C" };
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(strings);
List<String> data = mapper.readValue(json,
mapper.getTypeFactory().constructCollectionType(List.class, String.class));
for (String string : data) {
System.out.println(string);
}
代码存在多个问题。
1) 首先让我们看看为什么会出现异常
Exception in thread "main" java.lang.IllegalArgumentException: Invalid type id 'A' (for id type 'Id.class'): no such class found
上面的错误表明它没有找到一些 Class 并将 A 称为无效类型 ID 'A',这似乎是 Json 中的一个问题。
问题是因为行
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
这为所有非最终类型启用了默认类型。默认类型打印 Object 的类型和 Object 的实际值,因此可以反序列化为相同的类型。声明它 NON_FINAL 不会添加 "natural" 类型,例如 String.
和
String [] stringsBack = (String [])objectMapper.readValue(json, Object.class);
现在反序列化 Json ["A"、"B"、"C"] 时,反序列化器不知道 json 要转换的对象也将 A 作为 Class 类型并试图找到它没有得到的 class。
2) 评论第一行可能会给出 ClassCastException 因为
objectMapper.readValue(json, Object.class);
会 return 一个 ArrayList 的对象,它不能转换为 String[]。
3) !strings.equals(stringsBack)
将始终 return 为真,因为 strings 和 stringsBack 都是 String[] 的不同对象。
更正以下代码中的所有内容即可
ObjectMapper objectMapper = new ObjectMapper();
//You can remove the below line if Default Typing is not Required.
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
String[] strings = { "A", "B", "C" };
try
{
String json = objectMapper.writeValueAsString(strings);
System.out.println(json);
String[] stringsBack = (String[]) objectMapper.readValue(json, new TypeReference<String[]>()
{});
if (!Arrays.equals(strings, stringsBack))
{
System.err.println("ERROR, stringsBack not the same!!!\n\n");
}
}
catch (IOException e)
{
e.printStackTrace();
}