3

このクラスはベンダーライブラリからのものです:

public class JsonParser {
    public <T> T parse(String json, Class<T> type) { ... }
}

これらは私のモデルです:

public class Video {
    @Key
    private String title;
    public String getTitle() {
        return title;
    }
}

public class Response<TResult> {
    @Key
    private TResult result;
    public TResult getResult() {
        return result;
    }
    // ...
}

このコードは機能します:

JsonParser parser = new JsonParser();
String json = "{ \"title\": \"Hello world\" }";
Video video = parser.parse(json, Video.class);

このコードは機能しません:(構文エラーResponse<Video>.class

JsonParser parser = new JsonParser();
String json = "{ \"result\" : { \"title\": \"Hello world\" } }";
Response<Video> videoResponse = parser.parse(reader, Response<Video>.class);

このコードは機能します:

public class VideoResponse extends Response<Video> {
}

...
JsonParser parser = new JsonParser();
String json = "{ \"result\" : { \"title\": \"Hello world\" } }";
Response<Video> videoResponse = parser.parse(reader, VideoResponse.class);

私の質問は、そのように作成せずに、Response<Video>クラスをparseパラメーターとしてメソッドに渡す方法VideoResponseです。(私のプログラムには、に似たモデルがたくさんありますVideo。コードを複製して空のクラス、、、などを作成したくVideoResponseありUserResponseませCommentResponseActivityResponse

4

2 に答える 2

5

Javaジェネリックの実装方法が原因で、ほとんどの場合、ジェネリック情報は実行時に失われます。これらのいわゆる再利用可能な型の例外の1つは、ジェネリッククラスの具体的な拡張です。最初の例:

public class Video {
    @Key
    private String title;
    public String getTitle() {
        return title;
    }
}

public class Response<TResult> {
    @Key
    private TResult result;
    public TResult getResult() {
        return result;
    }
    // ...
}

resultパーサーは、プロパティがどのタイプであるかを判別できないため、プロパティを逆シリアル化できません(この情報は実行時に利用できないため)。基本的に、解析はを参照するだけでjava.lang.Object、JSONデータをプルするためにインスタンス化するタイプを決定できません。私はあなたがすでにこれが事実であると疑っていると思います、それ故にこの呼び出しをする試み:

Response<Video> videoResponse = parser.parse(reader, Response<Video>.class);

上記の行では、特定の応答がでパラメーター化されていることをパーサーに伝えようとしていますがVideo、残念ながらJavaにはジェネリッククラスリテラルの構文がないため、コードはコンパイルされません。

2番目の例では:

public class VideoResponse extends Response<Video> {
}

Response<Video> videoResponse = parser.parse(reader, VideoResponse.class);

ジェネリッククラスの具体的な拡張を作成しました。このような拡張機能の場合、ジェネリック型情報は実行時に利用できるため、パーサーはJSONデータを逆シリアル化するためにインスタンス化する必要があるものを判別できます。

これはすべて、実際の質問の背景情報です。

私の質問は次のとおりです。そのようなVideoResponseを作成せずに、応答クラスをパラメーターとして解析メソッドに渡す方法

使用しているJSONライブラリについて言及していませんが、一般的なライブラリのほとんどで、逆シリアル化メソッドには、一般にスーパータイプトークンと呼ばれるものを受け入れるオーバーライドバージョンがあります。スーパータイプトークンは、基本的に、上記で説明したものと同様に、クラスの単なる具体的な拡張です。たとえば、Jacksonでは、次のようにJSONを逆シリアル化します。

Response<Video> response = new ObjectMapper().readValue(
    jsonString, // JSON data
    new TypeReference<Response<Video>>() {} // super type token, implemented by anonymous class
);

JSONライブラリのドキュメントで同様のものを確認する必要があります。

于 2013-03-24T06:40:49.760 に答える
0

Javaジェネリック型の「型消去」のため、代わりに次のように型キャストを明示的に使用する必要があります。

Response<Video> videoResponse = (Response<Video>) parser.parse(reader, Response.class);

コンパイル警告が表示されますが、問題ありません。

于 2013-03-24T06:19:38.127 に答える