Jersey/JAX-RS客户端为什么无法处理泛型?

4
我有一个Jersery/JAX-RS客户端,它会访问一个RESTful API(JSON),该API应返回我的POJO列表:
// Hits: GET localhost:8080/myapp/fizz/widget/{widget_id}
@Override
public List<Widget> getWidgetsByUser(Long id) {
    return webResource.path("fizz").path("widget").path(id.toString()).get(List.class);
}

同时,需要一个驱动程序来测试客户端:

public class Driver {
    public static void main(String[] args) {
        Driver d = new Driver();
        d.run();
    }

    public void run() {
        MyAppService myService = getSomehow();

        List<Widget> widgets = myService.getWidgetResource().getWidgetsByUser(2L);
        for(Widget widget : widgets) {
            System.out.println("\t...and it found Widget #" + widget.getCaseId());
        }
    }
}

当我运行这个程序时,我得到了以下结果:
Exception in thread "main" java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to com.me.myapp.Widget
    <stack trace omitted for brevity>

异常是从for循环中抛出的:
for(Widget widget : widgets) {

这告诉我客户端有点运行,但我的配置不正确。

所以,要么Jersey尝试返回纯JSON并且没有尝试将其映射回Widget列表,要么我错误地调用了get(Class<?>)方法。 有什么想法吗?


1
这很容易理解 - 你正在告诉Jersey(可能是在Jackson下)将响应体转换为List。除了选择框架想要用于列表元素的内容之外,你还能期望框架做什么呢? - Pavel Horal
谢谢@PavelHoral (+1) - 那么我如何配置Jersey以返回List<Widget> - IAmYourFaja
你可以通过引入一个WidgetCollection对象并将其列表作为属性来解决这个问题(我认为这是一种常见的做法)。除此之外,我建议你查阅Jersey文档。但你可能需要阅读Jackson的解决方案(TypeReference),但这可能与Jersey的API不兼容。 - Pavel Horal
1个回答

8

Pavel Horal的评论是正确的。如果没有已知类型,Jackson(底层反序列化程序)将映射到LinkedHashMap,因此它将返回List<LinkedHashMap>

修复:

对于通用类型,我们应该使用另一个get()方法,它接受一个GenericType参数。所以我们应该做一些像这样的事情

...get(new GenericType<List<Widget>>(){});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接