0

我们将 Jersey/Jackson 用于我们的 REST 应用程序。传入的 JSON 字符串由 Jackson 映射到后端的 @Entity 对象以进行持久化。

问题来自我们用于所有实体的基类。它有一个受保护的 id 属性,我们也想通过 REST 交换它,这样当我们发送一个具有依赖关系的对象时,hibernate 会自动通过它们的 id 获取这些依赖关系。

然而,Jackson 不会访问 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 配置,因为这是我能想到的唯一可能出错的地方,如果我所描述的行为实际上应该是可能的,而无需向设置器(如我的回答中所述):

<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>
4

2 回答 2

2

所以,已经找到了解决方案:

必须@XmlElement(name="id")在所有覆盖的 ID 设置器上使用:

@XmlElement(name="id")
public void setId(Long id) {
    super.setId(id);
}
于 2012-09-28T10:27:16.120 回答
0

不,它应该按原样工作。Jackson 序列化程序查看实际的运行时类(包括所有基类属性),并且应该看到 getter(“getId()”)。所以其他事情正在发生。

基于解决方案,我想知道您是否可能不使用基于 Jackson POJO 的映射,而是使用其他东西......

于 2012-09-28T20:45:33.847 回答