Jersey response for empty list is null instead of

2019-04-11 18:22发布

问题:

I have a JAX-RS REST service using Jersey. I use JAXB for JSON marshalling (ie. @XmlRootElement) One of the method returns a list of objects persisted with JPA.

When this list contains entries it works as I expect. Example:

{"androidDevice":[{"email":"dagfinn.parnas@d2.no","timeCreated":"2012-10-19T
22:41:26.862+02:00"},{"email":"dagfinn.parnas@d1.com","timeCreated":"2012-10-
19T22:41:38.093+02:00"}]}

However, if the list is empty (or null) I would expect it to return {}.

Instead it returns null. Example:

$ curl  -i -H "Accept: application/json" http://....
HTTP/1.1 200 OK
Content-Type: application/json

null

Here is the code

    @GET
@Produces( { MediaType.APPLICATION_JSON ,  MediaType.APPLICATION_XML})
public List<AndroidDevice> getAndroidDevices() {
    logger.info("getAndroidDevices method called");


    EntityManager entityManager = entityMangerFactory.createEntityManager();  
    List<AndroidDevice> resultList = entityManager.createNamedQuery(AndroidDevice.QUERY_ALL_ENTRIES,  
            AndroidDevice.class).getResultList();  

    //avoid returning content null. (doesn't work)
    if(resultList==null){
        resultList=new ArrayList<AndroidDevice>();
    }

    return resultList;
}

Is there any way to get Jersey to return an empty JSON list (besides hardcoding a ResponseBuilder) ?

Should I instead provide a different response code for such events?

Update: Got a tips through twitter about this bug report which concludes with that they won't fix it http://java.net/jira/browse/JERSEY-339

Update2: In addition to the solution below, since I was using an Application for configuration (refered to in web.xml), I had to manually add the Provider class there. Here is the relevant code.

public class JAXRSApplication extends Application {

    @Override
    public Set<Class<?>> getClasses() {
        Set<Class<?>> set = new HashSet<Class<?>>();
        //Add all endpoints to this set
        set.add(AndroidDeviceEndpoint.class);
        //Add Providers
        set.add(JAXBContextResolver.class);
        return set;
    }   
}

回答1:

To achieve more important JSON format changes, you will need to configure Jersey JSON procesor itself. Various configuration options could be set on an JSONConfiguration instance. The instance could be then further used to create a JSONConfigurated JSONJAXBContext, which serves as a main configuration point in this area. To pass your specialized JSONJAXBContext to Jersey, you will finally need to implement a JAXBContext ContextResolver:

@Provider
public class JAXBContextResolver implements ContextResolver<JAXBContext> {
    private final JAXBContext context;
    private final Set<Class> types;
    private Class[] ctypes = { AndroidDevice.class}; //your pojo class
    public JAXBContextResolver() throws Exception {
        this.types = new HashSet(Arrays.asList(ctypes));
        this.context = new JSONJAXBContext(JSONConfiguration.natural().build(),
                ctypes); //json configuration
    }

    @Override
    public JAXBContext getContext(Class<?> objectType) {
        return (types.contains(objectType)) ? context : null;
    }
}

refer to jersey official document for detailed information.



回答2:

I have the same issue when restful service return null. All I did is to check the list size. If the size of the list is 0, I use the following:

return Response.ok("{}", req.getContentType()).status(Response.Status.OK); 

It returns "{}" in the body. My restkit client is happy with it now.



回答3:

I encountered the same issue. In Jersey 1.09 an empty array is sent as null while a filled array is written correctly. Now I use Jersey 1.19.4 and in this version an empty array is written correctly as {}.



标签: rest jersey