Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deserializing JSON with Jersey and MOXy into a List collection

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!

like image 612
iresprite Avatar asked Aug 14 '14 14:08

iresprite


1 Answers

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
like image 163
Paul Samsotha Avatar answered Nov 14 '22 22:11

Paul Samsotha