我正在使用Java和Jersey编写一个RESTful Web服务,其中服务将接受XML或JSON输入。 Jackson被用作JSON解串器,并被集成到Jersey配置中。Jackson相当于@XmlSeeAlso
其中一个端点是对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) {...}
然后我可以发布,看起来像<firstAction/>
一个XML片段,我的方法将被调用与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:根目录名称“第一-action'与类型[简单类型,类com.alu.openstack.domain.compute.server.actions.BaseAction]不符合预期('action')“
不幸的是,因为我试图与别人的API我无法更改我的示例输入 - { "first-action": null }
必须工作,并将类FirstAction的对象传递给我的方法。 (该动作没有任何字段,这就是为什么null不应该成为问题 - 这是重要的类的类型)。
以与XML反序列化相同的方式使JSON反序列化工作的正确方式是什么?
@ JsonTypeInfo似乎是用增加字段来增加内容以包含类型信息。正如问题中所述,我正在编写其他人的API的兼容实现,所以我无法更改模式,并且不幸的是添加字段不是一个选项。除非我错过@ JsonTypeInfo可以做的事 - 在这种情况下,你可以举个例子吗? – 2012-08-16 12:08:47
请看'@ JsonTypeInfo'。这是你需要的。它不需要在POJO中添加属性;它只会将它包含在JSON中,这是你可以控制的东西。另外,不要试图保持XML和JSON看起来尽可能相同:JSON和XML数据模型是不同的(阻抗),因此相同逻辑内容的自然结构自然不同。 – StaxMan 2012-08-16 17:13:21