如何使用特定的自定义objectMapper / JsonSerializer进行特定的requestMapping

时间:2017-12-04 07:39:19

标签: json spring-mvc jackson

我知道杰克逊允许我们为特定的域/实体/模型使用自定义序列化器,如下所示:

@JsonSerialize(using = CustomSerializer.class)
public class SimpleDomain {

}

并且,是否有任何想法为某些requestMapping指定自定义序列化程序, (仅针对特定的requestMapping(该方法),而不是设置全局objectMapper。)像这样:

@RequestMapping(method = RequestMethod.GET, value = "hello") 
@JsonSerialize(nullsUsing = NullToEmptyStrSerializer.class)
public @ResponseBody
Object get() {
    return new HashMap<String, Object>() {{
        put("aa", null);
        put("bb", "");
    }};
}

我执行上面的代码,它返回:

{
    "aa": null,
    "bb": ""
}

而不是:

{
    "aa": "",
    "bb": ""
}

我想要的。

NullToEmptyStrSerializer:

public class NullToEmptyStrSerializer extends JsonSerializer {
    @Override
    public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException, JsonProcessingException {
        gen.writeString("");
    }
}

或者,我可以在NullToEmptyStrSerializer中获取HttpServletRequest,如果是,我可以在NullToEmptyStrSerializer中过滤。

2 个答案:

答案 0 :(得分:0)

这可能是已知的限制(@JsonSerialize nullUsing选项不适用于String属性)并在此github issue中报告。

计划在jackson 2.9.3 and 2.8.11发布。

  

修复将在2.9.3中,但我也将其反向移植到2.8分支以防万一   2.8.11可能会在某个时候发布。

答案 1 :(得分:0)

最后,我自己发现了它。 我意识到了这一点:

  

或者,我可以在NullToEmptyStrSerializer中获取HttpServletRequest,如果是,我可以在NullToEmptyStrSerializer中过滤。

我的目的:

自定义将null转换为""以获取特定网址(RequestMapping

我的解决方案:

  1. 定义一个bean以保持ApplicationContext存储在静态字段中,也就是静态getter:

    @Component
    public class ContextHolder {
        private static ApplicationContext applicationContext;
    
        @Resource
        public void setApplicationContext(ApplicationContext applicationContext) {
            ContextHolder.applicationContext = applicationContext;
        }
    
        public static ApplicationContext get(){
            return applicationContext;
        }
    }
    
  2. 在下面定义一个bean,这个bean将为每个请求创建,因此,我将ServletRequest存储在这个bean中。

    @Component("servletRequestHolder")
    @Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
    public class ServletRequestHolder {
    
        @Resource
        private HttpServletRequest request;
    
        public HttpServletRequest getRequest(){
           return request;
        }
    }
    
  3. 然后,需要一个序列化器。

    public class NullToEmptyStringSerializer extends JsonSerializer.None {
    
        public static List<String> convertUrls = new ArrayList<String>(){{
            add("/hello");
        }};
    
        @Override
        public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
            HttpServletRequest request = ContextHolder.get().getBean(ServletRequestHolder.class).getRequest();
            if (request != null) {
                String currentUrl = request.getRequestURI();
                boolean match = convertUrls.contains(currentUrl);
                if (match) {
                    gen.writeString("");
                } else {
                    gen.writeObject(null);
                }
            } else {
                gen.writeObject(null);
            }
        }
    }
    
  4. 将Serializer添加到objectMapper:

    DefaultSerializerProvider.Impl sp = new DefaultSerializerProvider.Impl();
    sp.setNullValueSerializer(new NullToEmptyStringSerializer()); 
    objectMapper.setSerializerProvider(sp);
    
  5. 最后,测试一下:

    @GetMapping({"hello", "hello1"})
    public Object get() {
        return new HashMap<String, Object>() {{
            put("a", null);
            put("b", "");
        }};
    }
    

    如果请求localhost:20000/hello,客户会收到:

    {
      "aa": "",
      "bb": ""
    }
    

    对于请求localhost:20000/hello1,客户端会收到:

    {
      "aa": null,
      "bb": ""
    }