我们使用Jersey / Jackson作为REST应用程序。传入的JSON字符串被映射到后端的@Entity对象,由Jackson保留。
问题来自我们用于所有实体的基类。它有一个受保护的id属性,我们也希望通过REST进行交换,这样当我们发送一个具有依赖关系的对象时,hibernate会自动通过它们的id获取这些依赖关系。
但是,即使我们在子类中覆盖它是公开的,杰克逊也不会访问setter。我们也试过使用@JsonSetter但无济于事。可能杰克逊只是查看基类,看到ID无法访问,所以它会跳过设置...
@MappedSuperclass
public abstract class AbstractPersistable<PK extends Serializable> implements Persistable<PK> {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private PK id;
public PK getId() {
return id;
}
protected void setId(final PK id) {
this.id = id;
}
子类:
public class A extends AbstractPersistable<Long> {
private String name;
}
public class B extends AbstractPersistable<Long> {
private A a;
private int value;
// getter, setter
// make base class setter accessible
@Override
@JsonSetter("id")
public void setId(Long id) {
super.setId(id);
}
}
现在,如果我们的数据库中有一些As,我们想通过REST资源创建一个新的B:
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Transactional
public Response create(B b) {
if (b.getA().getId() == null)
cry();
}
使用JSON字符串,例如{"a":{"id":"1","name":"foo"},"value":"123"}
。
传入的B将具有A引用但没有ID。
有没有办法告诉杰克逊要么忽略基类设置器,要么告诉它使用子类设置器?
我刚刚发现@JsonTypeInfo
,但我不确定这是我需要的或如何使用它。
感谢您的帮助!
修改
StaxMan让我担心我在这里遗漏了一些东西,所以我将添加我的servlet配置,因为这是我能想到的唯一可能出错的地方,如果我所描述的行为实际上可以在不添加XML的情况下实现对二传手的注释(如我的回答所述):
<servlet>
<servlet-name>jersey-serlvet</servlet-name>
<servlet-class>
com.sun.jersey.spi.spring.container.servlet.SpringServlet
</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>path.to.rest.resources</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jersey-serlvet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
答案 0 :(得分:2)
所以,找到了解决方案:
必须在所有重写ID设置器上使用@XmlElement(name="id")
:
@XmlElement(name="id")
public void setId(Long id) {
super.setId(id);
}
答案 1 :(得分:0)
不,它应该按原样运作。 Jackson序列化程序查看实际的运行时类(包括所有基类属性),并且应该看到getter(“getId()”)。 所以其他事情正在发生。
基于解决方案,我想知道你是否可能没有使用基于Jackson POJO的映射,而是其他一些......