Reputation: 195
I have a list of ids which I need to pass as an argument to be displayed in JSON format. Specifically, i put the values in a List and would like my GET method to return them as:
[ 1, 5, 12,...]
I tried using GenericList, but I get a MessageBodyWriter error:
MessageBodyWriter not found for media type=application/json, type=class java.util.ArrayList, genericType=java.util.List<java.lang.Long>.
I'm using Jersey 2.16, and I've had no problems outputting lists of custom classes. The code is here:
@GET
@Path("{name}")
@Produces(MediaType.APPLICATION_JSON)
public Response getUsersByName(@PathParam("name") String name){
List<Long> userIds = userService.getUserssByName(name);
GenericEntity<List<Long>> list = new GenericEntity<List<Long>>(userIds){};
return Response.ok(list).build();
}
UserService queries a hashmap for all the users whose name matches a certain name and returns a list of their keys:
public List<Long> getUserssByName(String name){
List<Long> ids = new ArrayList<>();
for (Entry<Long, User> entry : users.entrySet()){
User user = entry.getValue();
if (user.getName().equals(name)){
ids.add(entry.getKey());
}
}
return ids;
}
How can I get that list to be displayed as I've stated above?
Upvotes: 1
Views: 8463
Reputation: 111
I think this explanation-answer will serve better than just "fixing" your code
By default, jersey provides a set of entity providers that can be used for given media types. For application/json
, the following types are provided by default:
byte[]
String
InputStream
Reader
File
DataSource
StreamingOutput
To add support for serialization of other types to json is a bit of a rocky slope with the tools you are currently working with. I'll explain...
Jersey is just a framework for developing RESTful web services in java. There was a time when REST didn't exist (or wasn't seen as useful) and before that concept came about there were already many concrete implementations to facilitate Http data transfer. JAX-RS was one of them. This was during a time when javascript was likely in its infancy and XML largely ruled the world wide web. JAX-RS wasn't designed to natively prevent type erasure, and type erasure is precisely what we are trying to achieve. For me to go through the extremely long-winded solution of implementing the behaviors in MessageBodyWriter would be reinventing the wheel, and no one likes to reinvent the wheel! But, if you are interested in writing your own entities, or you are interested in learning what entities are and how to customize them, head over to https://jersey.java.net/documentation/latest/message-body-workers.html. Reading this document will outline what exactly is going on with your issues.
Choose a service. Learn it, and do not reinvent the wheel. There are many services out there that can achieve this. My favorite tool is Gson. It is a Java library developed by Google to convert Java objects into their JSON representation and vice versa.
Want to know how simple this is to fix your code?
@GET
@Path("{name}")
@Produces(MediaType.APPLICATION_JSON)
public Response getUsersByName(@PathParam("name") String name){
List<Long> userIds = userService.getUserssByName(namee);
Type listType = new TypeToken<List<Long>>() {}.getType();
Gson gson = new Gson();
String userIdList = gson.toJson(userIds, listType);
return Response.ok(userIdList).build();
}
Now, jersey supports application/json for String entity responses. Pretty much all of your responses will be represented as a String, type erasure is prevented, and you become a more happy developer.
Hope this helps!
Upvotes: 3
Reputation: 936
You have to convert the list to array.
@GET
@Path("{name}")
@Produces(MediaType.APPLICATION_JSON)
public Response getUsersByName(@PathParam("name") String name){
List<Long> userIds = userService.getUserssByName(namee);
Long[] userIdArray = userIds.toArray();
return Response.ok(userIdArray).build();
}
Upvotes: 0