使用Jersey和MOXy反序列化JSON为一个列表集合

8

我想把JSON对象放进一个集合中(我选择了List)。通过创建带有适当的getter和setter的BuiltCharacter,我已经能够将JSON响应解组成单个POJO。对于一组JSON元素,我尝试了以下方法:

List<BuiltCharacter> characters = response.readEntity(new GenericType<List<BuiltCharacter>>(){});

并且

List<BuiltCharacter> characters = client.target(uri).request(MediaType.APPLICATION_JSON).get(new GenericType<List<BuiltCharacter>>(){});

使用这些方法得到了以下结果:

在主线程中发生异常:java.lang.ClassCastException: BuiltCharacter 无法转换为 java.util.List

我最初使用了 Character 作为类名,但被提醒那是一个保留的类名。尽管如此,我仍然无法弄清楚发生了什么!


你试图反序列化的JSON长什么样子?它真的是一个数组吗? - Michal Gajdos
@MichalGajdos,这是我正在使用的示例:http://census.soe.com/get/ps2:v2/character/?character_id=5428010618020694593,5428010618035589553如果我尝试为此使用单个POJO,则上面两个代码示例实际上都将成功将两个JSON元素读入单个对象中。因此,当我查找character.first_lower时,它将返回"Dreadnaut"和"Daddy"。这很令人困惑! - iresprite
你能分享一些更多的代码吗?也许整个方法甚至是REST资源类? - Anton
1
嗨,我已经开始了这个悬赏。你可以在这里看到一个例子:http://krishantha.net/notes/restfull-services-in-java-with-jersey-part-3/。不起作用的是方法`public List<SalesType> getSalesType() { WebTarget target = client .target("http://localhost:8080/SalesMonitor/webapi/"); List<SalesType> response = target.path("saletypes") .request(MediaType.APPLICATION_JSON).get(new GenericType<List<SalesType>>(){}); System.out.println(response); return response; },我得到了SalesType cannot be cast to java.util.List`。 - George
1
@George 请将以下内容作为答案发布(并注明这只是参考,请稍后删除):(1) 您的资源类(2)SalesType 类(3)您的依赖关系。我无法重现问题。 OP链接的JSON是一个JSON对象,它不能映射到List。它需要是一个JSON数组。 - Paul Samsotha
我已经测试了Jersey/MOXy 2.2 - 2.14(懒得更新到2.17),并且它能正常工作,只要资源类返回了一个 List<SalesType> - Paul Samsotha
1个回答

2

回答有关悬赏问题,但似乎与原帖中的问题相同

看了你提供的链接,所有示例都返回SalesType,而不是List<SalesType>。你不能期望将SalesType转换为List<SalesType>。如果从你的资源类返回SalesType,则会出现异常。

即使从原帖的链接中,JSON也以JSON对象的形式出现。 List不映射到JSON对象({}),而是映射到JSON数组([])。

如果您想要一个SalesType列表,则只需从资源中返回列表。以下是完整示例:

import java.util.*;
import javax.ws.rs.*;
import javax.ws.rs.core.*;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.junit.Test;

class SalesType {
    public String test;
}
public class MOXyTest extends JerseyTest {

    @Path("test")
    public static class TestResource {

        @GET
        @Produces(MediaType.APPLICATION_JSON)
        public Response getSalesTypeList() {
            List<SalesType> list = new ArrayList<>();
            SalesType sales = new SalesType();
            sales.test = "test";
            list.add(sales);
            list.add(sales);
            return Response.ok(
                   new GenericEntity<List<SalesType>>(list){}).build();
        }
    }

    @Override
    public Application configure() {
        return new ResourceConfig(TestResource.class);
    }

    @Test
    public void testGetSalesTypeList() {
        List<SalesType> list = target("test").request()
                .get(new GenericType<List<SalesType>>(){});
        for (SalesType sales: list) {
            System.out.println(sales.test);
        }
    }
}

这是我使用的两个依赖项(利用Jersey Test Framework)。

<dependency>
    <groupId>org.glassfish.jersey.test-framework.providers</groupId>
    <artifactId>jersey-test-framework-provider-inmemory</artifactId>
    <version>${jersey2.version}</version>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-moxy</artifactId>
    <version>${jersey2.version}</version>
</dependency>

你的问题可以通过在上面的例子中从资源类中返回 sales 来轻松地复现。目前上面的代码可以工作,但是为了看到错误,如果你替换 GenericEntity (它是用于包装在 Response 中返回的通用类型的包装器),你将会看到相同的错误。

java.lang.ClassCastException: com.stackoverflow.jersey.test.SalesType
                              cannot be cast to java.util.List

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