2013-03-24 61 views
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众多车型,我不想重复我的代码创建空类VideoResponseUserResponseCommentResponseActivityResponse等)

回答

4

由于Java泛型的实现方式,在大多数情况下,通用信息在运行时会丢失。这些所谓的reifiable类型的例外之一是泛型的具体扩展。为了您的第一个例子:

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的没有按没有泛型类文字的语法,所以代码不能编译。

在你的第二个例子:

public class VideoResponse extends Response<Video> { 
} 

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

您已经创建了通用类的具体延伸。对于这样的扩展,泛型类型信息在运行时可用,所以解析器可以确定它需要实例化以便反序列化JSON数据。

这一切的背景信息,以您的实际问题:

我的问题是:如何通过Response类解析方法,参数不一样,

创建VideoResponse你忘了提什么JSON库,但在大多数流行的库中,反序列化方法有一个被覆盖的版本,它接受通常称为超级类型令牌。超级类型令牌基本上只是一个类的具体扩展,类似于我上面描述的。在杰克逊,例如,你会反序列化JSON是这样的:

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

您应该检查你的JSON库文档类似的话。

+0

感谢您的帮助。我使用的库是Google的JsonObjectParser http://javadoc.google-http-java-client.googlecode.com/hg/1.13.1-beta/com/google/api/client/json/JsonObjectParser.html。基础,它使用JsonParser http://javadoc.google-http-java-client.googlecode.com/hg/1.13.1-beta/com/google/api/client/json/JsonParser.html,我会尝试使用' #parse(Object,CustomizeJsonParser)' – 2013-03-24 07:23:51

+0

@JacobDam - 它看起来像库可以使用'Type'反序列化。获得该方法的一种方法是拉入Google GoGles库并执行类似'new TypeToken >(){}。getType()'。当然,如果你拉入Gson库,你可以用它来解析! – Perception 2013-03-24 07:33:10

0

由于Java的泛型类型的“类型擦除”,你应该使用类型明确如下代替:

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

它会引入编译警告,但没关系。

+0

这不能正常工作。 'parser.parse(reader,Response.class)'将产生一个带有'.result'的Response对象不是'Video'对象。但是这个对象被分配给'Response