我正在使用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