我正在使用 Java 和 Jersey 编写一个 RESTful Web 服务,该服务将接受 XML 或 JSON 输入。Jackson 用作 JSON 反序列化器,并集成到 Jersey 配置中。
其中一个端点是对 URL 的 POST 请求,其中的内容可以是几个不同的 Java 类之一,并且有一个公共基类。这些带有 XML 注释的类是:
@XmlRootElement(name = "action")
@XmlAccessorType(XmlAccessType.NONE)
@XmlSeeAlso({ FirstAction.class, SecondAction.class, ThirdAction.class })
public abstract class BaseAction {
}
@XmlRootElement(name = "first-action")
@XmlAccessorType(XmlAccessType.NONE)
public class FirstAction extends BaseAction implements Serializable {
}
// Likewise for SecondAction, ThirdAction
在我的资源中,我可以声明一个方法,例如:
@POST
@Path("/{id}/action")
public Response invokeAction(@PathParam("id") String id, BaseAction action) {...}
然后我可以发布一个看起来像的 XML 片段,<firstAction/>
我的方法将被一个FirstAction
实例调用。到现在为止还挺好。
我苦苦挣扎的地方是让 JSON 反序列化与 XML 反序列化一样无缝地工作。在@XmlSeeAlso
注释对于使 XML 反序列化正常工作至关重要的地方,似乎 JSON 的等价物是@JsonSubTypes
. 所以我这样注释类:
// XML annotations removed for brevity, but they are present as in the previous code snippet
@JsonSubTypes({ @JsonSubTypes.Type(name = "first-action", value = FirstAction.class),
@JsonSubTypes.Type(name = "second-action", value = SecondAction.class),
@JsonSubTypes.Type(name = "third-action", value = ThirdAction.class) })
public abstract class BaseAction {
}
@JsonRootName("first-action")
public class FirstAction extends BaseAction implements Serializable {
}
// Likewise for SecondAction, ThirdAction
然后我给它我的测试输入:{ "first-action": null }
但我能得到的是:
“org.codehaus.jackson.map.JsonMappingException:根名称'first-action'与类型[简单类型,类com.alu.openstack.domain.compute.server.actions.BaseAction]的预期('action')不匹配"
不幸的是,因为我试图与其他人的 API 兼容,所以我无法更改我的示例输入 -{ "first-action": null }
必须工作,并向我的方法提供 FirstAction 类的对象。(该操作没有任何字段,这就是为什么 null 不应该成为问题的原因——重要的是类的类型)。
让 JSON 反序列化以与 XML 反序列化相同的方式工作的正确方法是什么?