使用 Jackson ObjectMapper 将子类名称序列化为 JSON,而不是超类
在以下将对象序列化为 JSON 的 Jackson/Java 代码中,我得到的是:
{"animal":{"x":"x"}}
然而,我真正想要得到的是:
{"dog":{"x":"x"}}
我可以对 AnimalContainer 做些什么,以便获得运行时类型 ("dog", "对象的“猫”),而不是“动物”)? (编辑:我知道地图名称来自 getter- 和 setter- 方法名称。) 我能想到的唯一方法是在 AnimalContainer 中每种 Animal 都有一个属性,所有这些 Animal 都有 setter 和 getter,并强制一次只能评估一个。但这违背了拥有 Animal 超类的目的,而且似乎是错误的。在我的真实代码中,我实际上有十几个子类,而不仅仅是“狗”和“猫”。有没有更好的方法来做到这一点(也许以某种方式使用注释)?我还需要一个反序列化的解决方案。
public class Test
{
public static void main(String[] args) throws Exception
{
AnimalContainer animalContainer = new AnimalContainer();
animalContainer.setAnimal(new Dog());
StringWriter sw = new StringWriter(); // serialize
ObjectMapper mapper = new ObjectMapper();
MappingJsonFactory jsonFactory = new MappingJsonFactory();
JsonGenerator jsonGenerator = jsonFactory.createJsonGenerator(sw);
mapper.writeValue(jsonGenerator, animalContainer);
sw.close();
System.out.println(sw.getBuffer().toString());
}
public static class AnimalContainer
{
private Animal animal;
public Animal getAnimal() {return animal;}
public void setAnimal(Animal animal) {this.animal = animal;}
}
public abstract static class Animal
{
String x = "x";
public String getX() {return x;}
}
public static class Dog extends Animal {}
public static class Cat extends Animal {}
}
In the following Jackson/Java code that serializes objects into JSON, I am getting this:
{"animal":{"x":"x"}}
However, what I actually want to get is this:
{"dog":{"x":"x"}}
Is there something I can do to AnimalContainer so that I get the runtime type ("dog", "cat") of the object, instead of "animal")? (Edit: I am aware that the map name comes from the getter- and setter- method names.) The only way I can think of to do it is within AnimalContainer to have an attribute of each type of Animal, have setters and getters for all of them, and enforce that only one is valued at a time. But this defeats the purpose of having the Animal superclass and just seems wrong. And in my real code I actually have a dozen subclasses, not just "dog" and "cat". Is there a better way to do this (perhaps using annotations somehow)? I need a solution for deserializing, as well.
public class Test
{
public static void main(String[] args) throws Exception
{
AnimalContainer animalContainer = new AnimalContainer();
animalContainer.setAnimal(new Dog());
StringWriter sw = new StringWriter(); // serialize
ObjectMapper mapper = new ObjectMapper();
MappingJsonFactory jsonFactory = new MappingJsonFactory();
JsonGenerator jsonGenerator = jsonFactory.createJsonGenerator(sw);
mapper.writeValue(jsonGenerator, animalContainer);
sw.close();
System.out.println(sw.getBuffer().toString());
}
public static class AnimalContainer
{
private Animal animal;
public Animal getAnimal() {return animal;}
public void setAnimal(Animal animal) {this.animal = animal;}
}
public abstract static class Animal
{
String x = "x";
public String getX() {return x;}
}
public static class Dog extends Animal {}
public static class Cat extends Animal {}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
根据本公告, Jackson 1.5 实现了完整的多态类型处理,并且 trunk 现在集成了该代码。
有两种简单的方法可以实现此目的:
As per this announement, Jackson 1.5 implements full polymorphic type handling, and trunk now has that code integrated.
There are two simple ways to make this work:
这可能不是您正在寻找的答案,但计划为 Jackson 版本 1.4 左右(即不是下一个版本 1.3,而是之后的版本)实现适当的“多态反序列化”(以及对其序列化的必要支持)那)。
对于当前版本,您必须实现自定义序列化器/反序列化器:我可能只定义用于反序列化的工厂方法,并为序列化器定义类型 getter(将“getAnimalType”或抽象基类中的任何内容定义为抽象,在子类中重写 - 或者即使只是在基类中实现,输出实例类的类名?)。
无论如何,以防万一,下面是使用 JSON 实现子类处理的潜在问题,并且没有模式语言(因为 json 并没有真正广泛使用):
这些是可以解决的问题,但解决起来并不容易。 :-)
This is probably not the answer you are looking for, but there are plans to implement proper "polymorphic deserialization" (and necessary support on serialization for it), for Jackson version 1.4 or so (i.e. not the next one, 1.3, but one after that).
For current version, you have to implement custom serializers/deserializers: I would probably just define factory method for deserialization, and type getter for serializer (define 'getAnimalType' or whatever in abstract base class as abstract, override in sub-classes -- or even just implement in base class, output class name of instance class?).
Anyway, just in case it matters, here are underlying problems wrt implementing handling of sub-classes with JSON, and without schema language (since json doesn't really have widely used one):
These are solvable problems, but not trivially easy to solve. :-)
这是我能想到的唯一方法,而且很丑陋。有更好的办法吗?
This is the only way I can think of to do it, and it is ugly. Is there a better way?