我通过在基类上添加注释启用了多态序列化支持。我能够成功地序列化一个单独的对象,它将类型信息作为序列化数据的一部分写入。然而,如果我将对象存储在一个列表中并序列化它,就不会发生同样的情况。
这个问题似乎在1.6.3(http://jira.codehaus.org/browse/JACKSON-362)中得到了修复。
我正在使用Jackson 2.3.2,仍然面临这个问题。
有人知道如何解决这个问题吗?
代码:
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY,property = "type")
@JsonSubTypes({@Type(value = Derived.class, name = "derived")})
public abstract class Base {
}
public class Derived extends Base {
private String field;
public String getField() {
return field;
}
public void setField(String field) {
this.field = field;
}
}
public class Test {
public static void main(String[] args) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
Derived d = new Derived();
d.setField("Name");
Base b = d;
System.out.println(mapper.writeValueAsString(b));
List<Base> list = new ArrayList<Base>();
list.add(d);
System.out.println(mapper.writeValueAsString(list));
}
}
输出:
{“type”:“derived”,“field”:“Name”}
[{“field“:”Name“}]
谢谢,
普拉文
我对对象数组也有同样的问题。对象[]不携带类型信息,但单个对象携带。很遗憾杰克逊没有自动处理这个问题。
两种可能的解决方案:1.类型化数组序列化工作正常:
Base[] myArray = Base[]{d};
mapper.writeValueAsString(myArray)
这实际上会产生预期的结果,因为Base[]具有类型信息。
串行器:
public class ObjectArraySerializer extends StdSerializer<Object[]> {
public ObjectArraySerializer(final Class<Object[]> vc) {
super(vc);
}
@Override
public void serialize(
final Object[] data,
final JsonGenerator gen,
final SerializerProvider provider) throws IOException {
gen.writeStartArray();
for (Object obj : data) {
gen.writeObject(obj);
}
gen.writeEndArray();
}
}
ObjectMapper配置:
ObjectMapper objectMapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addSerializer(
Object[].class,
new ObjectArraySerializer(Object[].class));
objectMapper.registerModule(module);
这个问题可以通过使用数组而不是列表来解决(因为列表确实可以擦除):
例如,上面的测试用例可以写成:
public class Test {
public static void main(String[] args) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
Derived d = new Derived();
d.setField("Name");
Base b = d;
System.out.println(mapper.writeValueAsString(b));
List<Base> list = new ArrayList<Base>();
list.add(d);
System.out.println(mapper.writeValueAsString(
list.toArray(new Base[list.size]) // <--This Part
));
}
}
答案就在 https://github.com/FasterXML/jackson-databind/issues/699
这是由于Java类型擦除:当序列化List时,Jackson看到的所有类型都是List(大致相当于List)。由于类型Object没有多态类型信息(注释),因此不会写入任何内容。所以这不是Jackson中的一个bug,而是Java类型擦除的一个不幸特性。它不适用于数组,因为它们保留元素类型信息(数组不是泛型的;不同类型的数组是不同的类,而泛型类型主要是编译时的语法糖)。
有三种主要的方法来处理这个问题:
pass full generic type using TypeReference (ObjectMapper has method like mapper.writerFor(new TypeReference<List<Base>>() { }).writeValue(....)
Sub-class List to something like public class BaseList extends ArrayList<Base>() { }, and pass that: this type WILL retain type information
Avoid using root-level List and Maps
我个人推荐做(3),因为这避免了与类型擦除相关的所有问题。在我看来,JSON根值应该始终是一个JSON对象,通常序列化为POJO从POJO序列化。
然而,方法(2)是可行的,这也是大多数用户所做的。它确实需要使用一个额外的助手类。
方法(1)可能有效,也可能无效;问题是强制类型信息也会影响实际的值序列化。因此,虽然它会添加类型id,但可能会导致某些属性不被序列化。
在Eclipse中使用参数化JUnit测试时,当我想重新运行一个测试时,遇到了一个问题。测试本身运行良好,虽然我可以从上下文菜单重新运行第一个测试,但可以重新运行第二个测试: 失败,并显示以下消息: JAVAlang.Exception:未找到匹配[{ExactMatcher:fDisplayName=test[1:A2]的测试-- 我很确定这是因为JUnit不喜欢我的数组;在某些情况下:我用它来
问题内容: 我正在尝试使用自定义将一些JSON反序列化为各种子类 我几乎遵循了这一点。 我的抽象基类: 而我的派生: 只是一个包含一些字符串常量的静态类。 JSON文件反序列化如下: 现在,我的问题是,每当我运行代码时,都会出现以下错误: 有问题的Json文件如下所示: 在我看来,反序列化嵌套对象有麻烦,我该如何解决? 问题答案: 首先,错过了您的json中的菜单项“ Submenus Test”
问题内容: 当数组包含字符串数据时,我在使用numpy时遇到一些琐碎的麻烦。我有以下代码: 现在,当我使用打印时,得到的响应是,显然不是Cat和Apple的预期输出。为什么会这样,如何获得正确的输出? 谢谢! 问题答案: Numpy要求字符串数组具有固定的最大长度。当您使用创建空数组时,默认情况下会将最大长度设置为1。你看你是否做; 它将显示“ | S1”,表示“一个字符的字符串”。随后的数组分配
问题内容: 哪两个代码片段正确创建并初始化了一个int元素的静态数组?(选择两个。) 一个。 B. C。 D. 答案:A,B 在这里即使D看起来是真实的,谁能让我知道为什么D是错误的。 问题答案: 正确答案是1和2(或者用您的符号表示A和B),而且正确的解决方案是: 解决方案D不会自动初始化数组,因为运行时会加载该类。它只是定义了一个静态方法(init),您必须在使用数组字段之前调用该方法。
问题内容: 是否可以使Java中的2D数组可序列化? 如果没有,我正在寻找将3x3 2D数组“翻译”为向量的向量。 我一直在玩矢量,但我仍然不确定如何表示。谁能帮我? 谢谢! 问题答案: Java中的数组是可序列化的,因此数组数组也可以序列化。 但是,它们所包含的对象可能不是,因此请检查数组的内容是否可序列化-如果不是,则使其可序列化。 这是一个使用整数数组的示例。 输出:
将多行字符串根据行拆分为数组。 使用 String.split() 和一个正则表达式来匹配换行符并创建一个数组。 const splitLines = str => str.split(/\r?\n/); splitLines('This\nis a\nmultiline\nstring.\n'); // ['This', 'is a', 'multiline', 'string.' , '']