Java と Jersey を使用して RESTful Web サービスを作成しています。サービスは XML または JSON 入力を受け入れます。Jackson は JSON デシリアライザーとして使用され、Jersey 構成に統合されています。
エンドポイントの 1 つは、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 フラグメントを POST できます。<firstAction/>
メソッドはインスタンスで呼び出されFirstAction
ます。ここまでは順調ですね。
私が苦労しているのは、JSON デシリアライゼーションを XML デシリアライゼーションと同じくらいシームレスに機能させることです。XML デシリアライゼーションを適切に機能させるためにアノテーションが重要である場合@XmlSeeAlso
、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 デシリアライゼーションと同じように動作させる正しい方法は何ですか?