Jackson对象映射 - 将传入的JSON字段映射到基类中的受保护属性

时间:2012-09-28 09:36:11

标签: java json rest inheritance jackson

我们使用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>

2 个答案:

答案 0 :(得分:2)

所以,找到了解决方案:

必须在所有重写ID设置器上使用@XmlElement(name="id")

@XmlElement(name="id")
public void setId(Long id) {
    super.setId(id);
}

答案 1 :(得分:0)

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

基于解决方案,我想知道你是否可能没有使用基于Jackson POJO的映射,而是其他一些......