10

在以下将对象序列化为 JSON 的 Jackson/Java 代码中,我得到了这个:

{"animal":{"x":"x"}}

但是,我真正想要得到的是:

{"dog":{"x":"x"}}

我可以对 AnimalContainer 做些什么,以便获得对象的运行时类型(“狗”、“猫”),而不是“动物”)? 编辑: 我知道地图名称来自 getter- 和 setter- 方法名称。)我能想到的唯一方法是在 AnimalContainer 中拥有每种动物的属性,具有 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 {} 
}
4

3 回答 3

11

根据这个公告,Jackson 1.5 实现了完整的多态类型处理,并且 Trunk 现在已经集成了该代码。

有两种简单的方法可以使这项工作:

  • 在超类型(此处为动物)中添加 @JsonTypeInfo 注释,或者
  • 通过调用 ObjectMapper.enableDefaultTyping() 配置对象映射器(但如果是这样,Animal 需要是抽象类型)
于 2010-02-08T02:02:39.357 回答
2

这可能不是您正在寻找的答案,但有计划为 Jackson 1.4 版左右(即不是下一个,1.3,而是之后的一个)实施适当的“多态反序列化”(以及对它的序列化的必要支持)那)。

对于当前版本,您必须实现自定义序列化器/反序列化器:我可能只是为反序列化定义工厂方法,并为序列化器键入 getter(将抽象基类中的“getAnimalType”或其他任何东西定义为抽象,在子类中覆盖 - 或甚至只是在基类中实现,输出实例类的类名?)。

无论如何,为了以防万一,这里是使用 JSON 实现子类处理的潜在问题,并且没有模式语言(因为 json 并没有真正广泛使用):

  • 如何将数据(bean 属性值)与元数据(类型信息只需要构造适当的子类)分开——必须保持分开,但 JSON 作为格式无法定义(可以使用命名约定)
  • 如何添加适当的注释来生成和使用此类元数据;并且不依赖于语言特定的功能(例如,不应该绑定到 java 类名)

这些都是可以解决的问题,但解决起来并不容易。:-)

于 2009-09-12T01:03:00.737 回答
0

这是我能想到的唯一方法,而且很丑陋。有没有更好的办法?

   @JsonWriteNullProperties(false)
   public static class AnimalContainer
   {
      private Animal animal;

      public Animal getCat()
      {
         return animal instanceof Cat ? animal : null;
      }
      public void setCat(Cat cat)
      {
         this.animal = cat;
      }
      public Animal getDog()
      {
         return animal instanceof Dog ? animal : null;
      }
      public void setDog(Dog dog)
      {
         this.animal = dog;
      }
      public Animal getFish()
      {
         return animal instanceof Fish ? animal : null;
      }
      public void setFish(Fish fish)
      {
         this.animal = fish;
      }
   }
于 2009-08-25T13:57:54.107 回答