我正在处理一个web项目,该项目使用一个静态ObjectMapper,它通过XML文件进行配置,应该在整个项目中生效。然而,我必须实现一个API来发送一个响应,无论设置如何,都不会忽略null属性。我的老板告诉我,他不希望创建另一个ObjectMapper,创建我自己的JSON编写器被认为是多余的,所以这也是被禁止的。这导致我被困在这里。我试过了。
Map<String, Object>resultMap = getResult();
try {
mapper.setSerializationInclusion(Include.ALWAYS);
response = mapper.writeValueAsString(resultMap);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
} finally {
if (ServiceConfig.isWriteNull()) {
mapper.setSerializationInclusion(Include.ALWAYS);
} else {
mapper.setSerializationInclusion(Include.NON_NULL);
}
}
要临时切换设置,它是有效的。但是考虑到映射器是异步使用的,更改全局配置肯定是个坏主意。我还想过在配置切换之前锁定映射器,但由于映射器是静态的,这可能是另一个坏主意。我希望有一些巧妙的方式,比如注释或参数神奇地影响单个执行。我想知道这是否可能?
您当前拥有的是危险的,因为您正在临时更改全局映射器的配置。这也会影响同时使用同一映射器实例进行序列化的其他线程。
然而,还有另一种方法可以实现你所需要的。ObjectMapper
实例有几种方法可以基于映射器创建ObjectWriter
实例。
Map<String, Object> resultMap = getResult();
try {
response = mapper
.writer(SerializationFeature.WRITE_NULL_MAP_VALUES)
.writeValueAsString(resultMap);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
正如@Stepan Stahlmann
在您的评论中所说,您还可以使用ObjectMapper#copy()
方法在全局实例的基础上创建一个临时的新ObjectMapper
实例。想法是一样的:使用全局ObjectMapper
作为根进行配置,并进行一些调整,以便生成符合API-Contract的JSON。
Map<String, Object> resultMap = getResult();
try {
response = mapper
.copy()
.setSerializationInclusion(Include.ALWAYS)
.writeValueAsString(resultMap);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
一种不同的方法
还有另一种方法我可以想到,我相信还有更多。您可以将resultMap
封装在一个类中,其中存在一些注释,这些注释应该会否决映射器的默认行为:
package example;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonValue;
import java.util.Map;
// Your inclusion rule
@JsonInclude(JsonInclude.Include.ALWAYS)
public class ResponseWrapper {
private final Map<String, Object> response;
public ResponseWrapper(Map<String, Object> response) {
this.response = response;
}
// tells Jackson to use the this a the actual value (so you don't see this wrapper in the json)
@JsonValue
public Map<String, Object> getResponse() {
return this.response;
}
}
Map<String, Object> resultMap = getResult();
try {
response = mapper.writeValueAsString(new ResponseWrapper(resultMap));
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
Map<String, Object>resultMap = getResult();
try {
response = mapper
.writer(SerializationFeature.WRITE_NULL_MAP_VALUES)
.writeValueAsString(resultMap);
} catch (JsonProcessingException e) { throw new RuntimeException(e);}