8

I'm trying to take JSON objects and put them into a collection (I picked List). I've been able to unmarshal the JSON responses into single POJOs by creating BuiltCharacter with the appropriate getters and setters. For an array of JSON elements, I tried the following approaches:

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

and

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

Using those approaches got me the following:

Exception in thread "main" java.lang.ClassCastException: BuiltCharacter cannot be cast to java.util.List

I originally used Character as the class name but was reminded that that is a reserved class name. Still, I can't figure out what's going on here!

iresprite
  • 181
  • 5
  • How does the JSON, you're trying to deserialize, look like? Is it really an array? – Michal Gajdos Aug 20 '14 at 12:53
  • @MichalGajdos, this is the example I'm using: http://census.soe.com/get/ps2:v2/character/?character_id=5428010618020694593,5428010618035589553 If I try to use a single POJO for this, both of my code examples above will actually successfully read both JSON elements into a single object. Thus, when I look for character.first_lower, it will return both "Dreadnaut" AND "Daddy". It's perplexing! – iresprite Aug 21 '14 at 14:09
  • Would you care to share a bit more of the code? Maybe the whole method or even the REST resource class? – Anton Sarov Apr 28 '15 at 08:49
  • 1
    Hi, I have started this bounty. You can see an example here: http://krishantha.net/notes/restfull-services-in-java-with-jersey-part-3/ . What doesn't work is the method `public List getSalesType() { WebTarget target = client .target("http://localhost:8080/SalesMonitor/webapi/"); List response = target.path("saletypes") .request(MediaType.APPLICATION_JSON).get(new GenericType>(){}); System.out.println(response); return response; }`, I get `SalesType cannot be cast to java.util.List` – George Apr 28 '15 at 08:52
  • 1
    @George please post as an answer (with a note of it being just reference; you can delete it later) (1) Your resource class (2) The SalesType class (3) Your dependencies. I cannot reproduce the problem. The JSON the OP linked to is a JSON object, which does not map to a List. It needs to be a JSON array. – Paul Samsotha Apr 28 '15 at 14:24
  • I've tested with Jersey/MOXy 2.2 - 2.14 (got lazy to go up to 2.17) and it works fine, given a `List` is actually returned from the resource class – Paul Samsotha Apr 28 '15 at 14:29

1 Answers1

2

Answer in regards to bounty, but it seems to be the same problem from the original post

Looking at the link you provided, all the examples return SalesType, and not a List<SalesType>. You can't expect a SalesType to be converted to a List<SalesType>. If you are returning SalesType from your resource class, the exception provided.

Even from the link for the original post, the JSON is coming in as JSON object. List doesn't map to a JSON object ({}), but instead a JSON array ([]).

If you want a list of SalesType, then simply return a list from the resource. Below is a complete example

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);
        }
    }
}

These are the two dependencies I used (making use of 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>

Your problem can easily be reproduced by return the sales in the resource class from the example above. The current code above works, but just to see the error, if you replace the GenericEntity (which is a wrapper for generic types being returned in a Response), you will see the same error

java.lang.ClassCastException: com.stackoverflow.jersey.test.SalesType
                              cannot be cast to java.util.List
Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720