自定义 Json 序列化程序而不是 Jersey 的默认序列化程序?
Customize Json serializer instead of Jersey's default?
我正在使用 Jersey 来实现 RESTful 网络服务。现在我 return 数据的 MediaType 是 JSON.
@GET
@Produces({MediaType.APPLICATION_JSON })
public Response service() {
return Response
.ok(entity)
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON)
.build();
}
这里我将CONTENT_TYPE
设置为json,我的实体将被Jersey框架转换为json。
现在我想自定义我的 json 回复。
例如:我想删除空元素或更改 Json 对象的键名。
默认 Jersey 的 Json 转换:
{
"cinter" : {
"state" : 1,
"checks" : 10,
}
}
我想要的:
{
"cin" : {
"st" : 1,
"cs" : 10,
}
}
我知道我可以使用 Jackson 图书馆的我自己的 ObjectMapper
来根据我的需要定制我的 Json。
但如果我想 JSON 以不同于 Jersey 的默认转换的方式进行转换,这是标准方法吗??
或者我可以更改 Jersey 的 ObjectMapper 中的参数吗??
我应该使用自己的 ObjectMapper
吗?
这是我对您的选择的看法。首先
So for every different response I should configure ObjectMapper
differently ?
如果你想像这样在不同的地方使用两个 json 版本
public Response getObject() // returns {"cinter" : {"state" : 1,"checks" : 10}}
public Response getShortNamesObject() // returns {"cin" : {"st" : 1,"cs" : 10}}
是的,你必须使用多个 ObjectMappers
。
但是如果你只想在任何地方使用 1 种表示,那么你可能可以使用自定义 mixin 为你设置一次 Jackson 类。无论如何,这里是您可以执行这两个选项的方法:让我们看一下只需要 1 json 版本
的简单案例
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;
}
}
此代码将为您在各处的 POJO 字段生成短名称。并为不同的请求实现不同的行为,我们必须像这样添加新的自定义注释:
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface MixIn {}
控制器将如下所示:
@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();
}
}
我们的 MixInJacksonJsonProvider
还会有 2 个 @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;
}
}
下面是演示代码供您玩:https://github.com/varren/jersey2-jacksonsetup/tree/master/src/main/java/ru/varren
我正在使用 Jersey 来实现 RESTful 网络服务。现在我 return 数据的 MediaType 是 JSON.
@GET
@Produces({MediaType.APPLICATION_JSON })
public Response service() {
return Response
.ok(entity)
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON)
.build();
}
这里我将CONTENT_TYPE
设置为json,我的实体将被Jersey框架转换为json。
现在我想自定义我的 json 回复。
例如:我想删除空元素或更改 Json 对象的键名。 默认 Jersey 的 Json 转换:
{
"cinter" : {
"state" : 1,
"checks" : 10,
}
}
我想要的:
{
"cin" : {
"st" : 1,
"cs" : 10,
}
}
我知道我可以使用 Jackson 图书馆的我自己的 ObjectMapper
来根据我的需要定制我的 Json。
但如果我想 JSON 以不同于 Jersey 的默认转换的方式进行转换,这是标准方法吗??
或者我可以更改 Jersey 的 ObjectMapper 中的参数吗??
我应该使用自己的 ObjectMapper
吗?
这是我对您的选择的看法。首先
So for every different response I should configure ObjectMapper differently ?
如果你想像这样在不同的地方使用两个 json 版本
public Response getObject() // returns {"cinter" : {"state" : 1,"checks" : 10}}
public Response getShortNamesObject() // returns {"cin" : {"st" : 1,"cs" : 10}}
是的,你必须使用多个 ObjectMappers
。
但是如果你只想在任何地方使用 1 种表示,那么你可能可以使用自定义 mixin 为你设置一次 Jackson 类。无论如何,这里是您可以执行这两个选项的方法:让我们看一下只需要 1 json 版本
的简单案例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;
}
}
此代码将为您在各处的 POJO 字段生成短名称。并为不同的请求实现不同的行为,我们必须像这样添加新的自定义注释:
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface MixIn {}
控制器将如下所示:
@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();
}
}
我们的 MixInJacksonJsonProvider
还会有 2 个 @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;
}
}
下面是演示代码供您玩:https://github.com/varren/jersey2-jacksonsetup/tree/master/src/main/java/ru/varren