【问题标题】:Customize Json serializer instead of Jersey's default?自定义 Json 序列化程序而不是 Jersey 的默认值?
【发布时间】:2016-09-17 07:10:05
【问题描述】:

我正在使用 Jersey 来实现 RESTful 网络服务。现在我返回数据的 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。

但是,如果我想以不同于 Jersey 的默认转换的方式进行 JSON 转换,这是标准的方法吗??

或者我可以更改 Jersey 的 ObjectMapper 中的参数吗??

我应该使用自己的ObjectMapper 吗?

【问题讨论】:

  • 你的 POJO 长什么样?因为使用@JsonProperty(name="cit") 等上面的字段名称可以轻松解决。如果你不能改变你的 pojo,那么是的,你必须在你身上使用自定义 Mixin 或序列化器ObjectMapper
  • @My POJO 有 JAXB 注释 (@XmlRootElement) 是的,我无法更改它们。因此,对于每个不同的响应,我应该以不同的方式配置 ObjectMapper 吗?关于ContextResolver 的任何想法?
  • 您不能更改它们,但您可以添加注释吗?如果可以的话,@JsonProperty 在属性上,@JsonRootName 在类上解决你的问题

标签: java json jersey jackson jax-rs


【解决方案1】:

这是我对您的选择的看法。首先

所以对于每个不同的响应,我应该配置 ObjectMapper 不一样?

如果你想像这样在不同的地方同时使用两个 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 还会有两个@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

【讨论】:

  • 除了短名称之外,我还希望在某些 Pojos 中具有其他配置,例如 objectMapper.WRAP_ROOT_VALUE,而在其他 Pojo 中可能没有。那么ObjectMapper 中提供的所有配置是否都可以通过 MixIn 类中的注解获得?
  • @SiddharthTrikha 这真的取决于你想要什么。例如,如果您希望 1 个 pojo 始终使用 WRAP_ROOT 而其他 pojo 没有相同的表示,则只需 1 个 objectmapper 即可。您可以更改您的类序列化程序或向您的类添加注释或使用 MixIn。真的没关系。但是如果你需要同一个 POJO 的多个 json 版本,那么你必须创建多个对象映射器并为它们使用不同的 mixins/serializers + 在你的控制器中使用自定义注释来指定哪个应该使用自定义版本。
猜你喜欢
  • 1970-01-01
  • 2015-02-09
  • 1970-01-01
  • 2019-04-28
  • 1970-01-01
  • 2014-12-18
  • 2019-05-07
  • 2014-02-15
  • 2015-07-28
相关资源
最近更新 更多