私はjsonrpc4jを使用していますが、行き詰まりました。私の問題を示すために小さな例を作りました:
抽象クラス:
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME)
@JsonSubTypes(value = { @JsonSubTypes.Type(value = Walnut.class) })
public abstract class Nut {
}
具体的なサブクラス:
public class Walnut extends Nut {
}
サービスのインターフェース:
public interface ServiceInterface {
public Nut getNut();
public void setNut(Nut nut);
}
サービス自体:
public class Service implements ServiceInterface {
public Nut getNut() { return new Walnut(); }
public void setNut(Nut nut) {}
}
サーバ:
JsonRpcServer rpcServer = new JsonRpcServer(new ObjectMapper(), new Service());
StreamServer streamServer = new StreamServer(rpcServer, 50, 1420,
50, InetAddress.getByName("127.0.0.1"));
streamServer.start();
クライアント:
JsonRpcClient jsonRpcClient = new JsonRpcClient(new ObjectMapper());
ServiceInterface remoteService = ProxyUtil.createClientProxy(
ServiceInterface.class.getClassLoader(),
ServiceInterface.class, jsonRpcClient,
new Socket(InetAddress.getByName("127.0.0.1"), 1420));
remoteService.getNut()を呼び出すと、すべてが期待どおりに機能し、ログが出力されます。
JSON-PRC Request: {"id":"6064348714687420633","jsonrpc":"2.0","method":"getNut"}
JSON-PRC Response: {"jsonrpc":"2.0","id":"6064348714687420633",
"result":{"@type":"Walnut"}}
remoteService.setNut(new Walnut())を呼び出すと、サーバーが例外をスローし、ログが出力されます。
JSON-PRC Request {"id":"9194853851254039397","jsonrpc":"2.0",
"method":"setNut","params":[{}]}
Error in JSON-RPC Service com.fasterxml.jackson.databind.JsonMappingException:
Unexpected token (END_OBJECT), expected FIELD_NAME:
missing property '@type' that is to contain type id (for class Nut)
プロキシはすべてのパラメーターを 1 つのオブジェクト配列にラップするため、パラメーターの型情報が欠落しています (この場合に情報の型が欠落している理由を理解するには、最後の質問を参照してください)。
目的のシリアライゼーションを達成するにはどうすればよいですか? デフォルトの入力を有効にして、ミックスインを介してObject.classに (@JsonTypeInfo で) 注釈を付けようとしましたが、両方とも失敗しました (以下の例外)。
デフォルトの入力が有効になっている場合 [ remoteService.getNut()、サーバー側でエラー]:
Exception while handling request
com.fasterxml.jackson.databind.JsonMappingException:
Unexpected token (START_OBJECT), expected START_ARRAY:
need JSON Array to contain As.WRAPPER_ARRAY type information for
class com.fasterxml.jackson.databind.JsonNode
デフォルトの入力が有効になっている場合 [ remoteService.setNut(new Walnut())、クライアント側でエラー]:
Exception in thread "main" java.lang.IllegalArgumentException:
Unexpected token (START_ARRAY), expected VALUE_STRING:
need JSON String that contains type id (for subtype of
com.fasterxml.jackson.databind.JsonNode)
mix-in [ remoteService.getNut()、サーバー側のエラー]:
Exception while handling request
java.lang.IllegalArgumentException:
Could not resolve type id 'DefaultErrorResolver$ErrorData'
into a subtype of
[simple type, class com.fasterxml.jackson.databind.JsonNode]
mix-in [ remoteService.setNut(new Walnut())、クライアント側でエラー]:
Exception in thread "main" java.lang.ClassCastException:
[Ljava.lang.Object; cannot be cast to
com.fasterxml.jackson.databind.JsonNode
何か案は?