Java 继承和方法重载的Jackson序列化问题

Java 继承和方法重载的Jackson序列化问题,java,json,serialization,jackson,jersey,Java,Json,Serialization,Jackson,Jersey,我将Jackson与Jersey+Jetty一起用于我的RESTful应用程序。jackson库是:jackson-annoations-2.8.0jackson-core-2.8.9和jackson-databind-2.8.9 我无法让Jackson输出子类的值。它总是输出继承类的值。尽管我明确地提供了具体的对象。这个场景有点难以正确表达,我希望下面的例子能更好地解释它 下面是序列化的类的伪代码: Parent0.java: class Parent0 { protected Chil

我将Jackson与Jersey+Jetty一起用于我的RESTful应用程序。jackson库是:
jackson-annoations-2.8.0
jackson-core-2.8.9
jackson-databind-2.8.9

我无法让Jackson输出子类的值。它总是输出继承类的值。尽管我明确地提供了具体的对象。这个场景有点难以正确表达,我希望下面的例子能更好地解释它

下面是序列化的类的伪代码:

  • Parent0.java:

    class Parent0 {
      protected Child0 child;
    
      public Parent0() {}
    
      public Child0 getChild() {
         return child;
      }
    
      public void setChild(Child0 child) {
         this.child = child;
      }
    }
    
  • Parent1.java:

    class Parent1 extends Parent0 {}
    
  • Child0.java:

    class Child0 {
      protected int id;
    
      public Child0() {}
    
      public void setId(int id) {
         this.id = id;
      }
    
      public int getId() {
         return this.id;
       }
    
       @Override
       public boolean equals(Object o) {
          if (this == o) return true;
          if (o == null || getClass() != o.getClass()) return false;
          Child0 child0 = (Child0) o;
          return id == child0.id;
       }
    
       @Override
       public int hashCode() {
          return Objects.hash(id);
       }
    }
    
  • Child1.java:

    class Child1 extends Child0 {
       private String childName;
    
       public Child1() {}
    
       public String getChildName() {
          return childName;
        }
    
        public void setChildName(String childName) {
           this.childName = childName;
        }    
    }
    
  • 在主控制器内部:

    Parent0 p0 = new Parent0();
    Child0 c0 = new Child0();
    c0.setId(0);
    p0.setChild(c0);
    
    Parent0 p1 = new Parent1();
    Child1 c1 = new Child1();
    c1.setId(1);
    c1.setChildName("C1");
    p1.setChild(c1);
    
    serializeAndPrint(p0); // #1
    serializeAndPrint(p1); // #2
    
输出:

    #1 Parent0.json
    {
        child: {
            id: 0
        }
    }

    #2 Parent1.json
    {
        child: {
            id: 1
        }
    }
预期:

    #2 Parent1.json
    {
        child: {
            id: 1,
            childName: "C1"
        }
    }

序列化由Jersey框架处理。我用
@products(MediaType.APPLICATION\ujson)
注释我的端点,它基本上负责转换

serializeAndPrint方法的实现是什么?
我编写了一个单元测试来重现这个问题:

public class JsonTest {

@Test
public void test() throws JsonProcessingException {
    ObjectMapper mapper = new ObjectMapper();

    Parent0 p0 = new Parent0();
    Child0 c0 = new Child0();
    c0.setId(0);
    p0.setChild(c0);

    Parent0 p1 = new Parent1();
    Child1 c1 = new Child1();
    c1.setId(1);
    c1.setChildName("C1");
    p1.setChild(c1);

    System.out.println(mapper.writer(new DefaultPrettyPrinter()).writeValueAsString(p0));
    System.out.println(mapper.writer(new DefaultPrettyPrinter()).writeValueAsString(p1));

}
}

输出正是您所期望的:

{
  "child" : {
  "id" : 0
  }
}
{
  "child" : {
   "id" : 1,
   "childName" : "C1"
   } 
}

看起来Jackson不是正在使用的JSON提供程序(如中所示)。您所说的那些依赖项(库)是不够的。它们只是Jackson的核心依赖项。Jackson确实有一个支持JAX-RS的库,如果您使用Jersey,那么Jackson JAX-RS支持库有一个Jersey包装器

如果您使用的是Jersey 2.x,那么您需要的依赖项是
Jersey media json jackson
。添加依赖项后,应在Jersey应用程序配置(web.xml或ResourceConfig)中注册
JacksonFeature
。目前,您可能正在使用其他一些JSON提供程序,但您并不知道。检查是否存在任何其他依赖项。如果你有除Jackson以外的任何其他产品,请将其删除。如果
jersey-media-json-jackson
是类路径中唯一的提供者,那么您不需要注册
JacksonFeature
,它将默认为使用的提供者

如果您使用的是Jersey 1.x,那么依赖项是
Jersey json
。添加依赖项后,需要在应用程序配置中(web.xml的init参数或ResourceConfig中)将
com.sun.jersey.api.json.POJOMappingFeature
属性设置为true


注意:如果您手动添加JAR,而不使用Maven这样的依赖关系管理器,那么在计算出您需要的所有JAR时需要做更多的工作,因为
jersey media json jackson
jersey json
都依赖于其他几个JAR。

序列化由jersey框架处理。我用
@products(MediaType.APPLICATION\ujson)
注释我的端点,它基本上负责转换。既然你的测试用例通过了,我想这和Jersey转换器有关,而不是Jackson本身。我将编辑我的问题以提供此信息。非常感谢。