I am using Jersey to implement RESTful webservice. Now the MediaType in which I return data is JSON.
@GET
@Produces({MediaType.APPLICATION_JSON })
public Response service() {
return Response
.ok(entity)
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON)
.build();
}
Here I set CONTENT_TYPE
to json and my entity will be converted to json by Jersey framework.
Now I want to customize my json response.
Eg: I want to remove the empty elements or change the keys name of my Json object. Default Jersey's Json conversion:
{
"cinter" : {
"state" : 1,
"checks" : 10,
}
}
What I want:
{
"cin" : {
"st" : 1,
"cs" : 10,
}
}
I know I can use Jackson library's my own ObjectMapper
to customize my Json according to my needs.
But is this the standard way to do it if I want JSON conversion in a different way than Jersey's default conversion ??
Or can I change paramaters in Jersey's ObjectMapper ??
Should I be using my own ObjectMapper
?
Here is my thoughts about your options. First of all
So for every different response I should configure ObjectMapper differently ?
If you want to use both json versions in different places like this
public Response getObject() // returns {"cinter" : {"state" : 1,"checks" : 10}}
public Response getShortNamesObject() // returns {"cin" : {"st" : 1,"cs" : 10}}
Than yep, you have to use multiple ObjectMappers
.
But if you just want to use 1 representation everywhere, then you probably will be able to setup Jackson once with custom mixin for you classes. Anyway here is how you can do both options: And lets look at simple case with just 1 json version needed
public class TestBean {
private String name;
private int id;
//getters and setters
}
public interface TestBeanMixin {
@JsonProperty("short_field_name")
String getName();
@JsonProperty("short_field_id")
int getId();
}
@Provider
@Priority(1)
public class MixInJacksonJsonProvider extends JacksonJaxbJsonProvider {
private static final ObjectMapper mapper = createMapper();
public MixInJacksonJsonProvider() {
setMapper(mapper);
}
private static ObjectMapper createMapper() {
final ObjectMapper result = new ObjectMapper();
result.addMixIn(TestBean.class, TestBeanMixin.class);
return result;
}
}
This code will produce short names for you POJO fields everywhere. and to implement different behavior for different request we have to add new custom annotation like this:
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface MixIn {}
Controller will look like this:
@Path("test")
public class MyResource {
@GET
@MixIn // <== Here is important part
@Produces(MediaType.APPLICATION_JSON )
public Response getShortName() {
return Response.ok(demoObj()).build();
}
@POST
@Produces(MediaType.APPLICATION_JSON )
public Response postLongName() {
return Response.ok(demoObj()).build();
}
}
And our MixInJacksonJsonProvider
will have 2 more @Override
:
//.. same as before
@Override
public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
return super.isReadable(type, genericType, annotations, mediaType) && hasMixInAnnotation(annotations);
}
@Override
public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
return super.isWriteable(type, genericType, annotations, mediaType) && hasMixInAnnotation(annotations);
}
public static boolean hasMixInAnnotation(Annotation[] annotations){
for(Annotation annotation: annotations){
if (annotation instanceof MixIn){
return true;
}
}
return false;
}
}
Here is demo code for you to play: https://github.com/varren/jersey2-jacksonsetup/tree/master/src/main/java/ru/varren
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With