jackson⾃定义序列化中null值的处理
在springboot中使⽤jackson,返回json数据时输出null值时按照属性类型输出具体形式
可以配置其⼀个MappingJackson2HttpMessageConverter类,这个类同时可以做另⼀个事情,防⽌ie对json数据当做⽂件进⾏下载。MappingJackson2HttpMessageConverter类中可以取到⼀个ObjectMapper,即jackson序列化的主类。
@Configuration
class JacksonHttpMessageConvertersConfiguration {
@Configuration
@ConditionalOnClass(ObjectMapper.class)
@ConditionalOnBean(ObjectMapper.class)
@ConditionalOnProperty(name=
HttpMessageConvertersAutoConfiguration.PREFERRED_MAPPER_PROPERTY,havingValue="jackson",matc
hIfMissing=true)
protected static class MappingJackson2HttpMessageConverterConfiguration {
@Bean
@ConditionalOnMissingBean(value= MappingJackson2HttpMessageConverter.class,ignoredType= {
"org.springframework.hateoas.mvc.TypeConstrainedMappingJackson2HttpMessageConverter",
"org.st.webmvc.alps.AlpsJsonHttpMessageConverter"})
public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter(
ObjectMapper objectMapper) {
return new MappingJackson2HttpMessageConverter(objectMapper);
}
}
}
上⾯的代码是springboot⾃带的配置⽂件,在packageorg.springframework.boot.autoconfigure.web包中
⽽我们可应通过⾃⼰配置的ObjectMapper来异化jackson在具体操作中解决null输出的类型
在MappingJackson2HttpMessageConverter中最为重要的就是writeInternal⽅法,代码如下
@Override
protected void writeInternal(Object object, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException {
JsonEncoding encoding = Headers().getContentType());
// The following has been deprecated as late as Jackson 2.2 (April 2013);
// preserved for the time being, for Jackson 2.0/2.1 compatibility.
@SuppressWarnings("deprecation")
JsonGenerator jsonGenerator =
JsonFactory().Body(), encoding);
// A workaround for JsonGenerators not applying serialization features
if (this.objectMapper.isEnabled(SerializationFeature.INDENT_OUTPUT)) {
jsonGenerator.useDefaultPrettyPrinter();
}
try {
if (this.jsonPrefix != null) {
jsonGenerator.writeRaw(this.jsonPrefix);
}
//此处进⾏序列化
this.objectMapper.writeValue(jsonGenerator, object);
}catch (JsonProcessingException ex) {
throw new HttpMessageNotWritableException("Could not write JSON: " + ex.getMessage(), ex);
}
}
this.objectMapper.writeValue(jsonGenerator, object);
可以发现在writeInternal⽅法中使⽤了this.objectMapper.writeValue(jsonGenerator, object);
进⾏序列化,跟进去,看到⼀句话:
_serializerProvider(config).serializeValue(jgen, value);
看来这个就是具体的序列化的⽅法了。
public void serializeValue(JsonGenerator jgen, Object value) throws IOException,
JsonGenerationException { if (value == null) { _serializeNull(jgen); return; }
Class cls = Class(); // true, since we do want to cache root-level typed serializers (ditto for null property) final JsonSerializerser = findTypedValueSerializer(cls, true, null);
try {
ser.serialize(value, jgen, this);
} catch (IOException ioe) { // As per [JACKSON-99], pass IOException and subtypes as-is
throw ioe;
} catch (Exception e) { // but wrap RuntimeExceptions, to get path information
String msg = e.getMessage();
if (msg == null) {
msg = "[no message for "+e.getClass().getName()+"]";
}
throw new JsonMappingException(msg, e);
}
}
在这⾥我们到了对于null处理的⽅法
if (value == null) { _serializeNull(jgen); return; }
_serializeNull(jgen)
继续跟进_serializeNull(jgen)
protected void_serializeNull(JsonGenerator gen)throwsIOException
{
JsonSerializer ser = getDefaultNullValueSerializer();
try{
ser.serialize(null,gen, this);
}catch(IOException ioe) {// no wrapping for IO (and derived)
throwioe;
}catch(Exception e) {// but others do need to be, to get path etc
String msg = e.getMessage();
if(msg ==null) {
msg ="[no message for "+e.getClass().getName()+"]";
}
reportMappingProblem(e,msg);
}
}
发现JsonSerializer ser = getDefaultNullValueSerializer()
JsonSerializer是⼀个抽象类,具有多个实现
public JsonSerializer getDefaultNullValueSerializer() {
return _nullValueSerializer;
}
ser.serialize(null,gen, this);
⽽在_nullValueSerializer中ser的具体实现是这样的
@Override public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider)throwsIOException,
JsonGenerationException
{
jgen.writeNull();
}
只要替换掉这个_nullValueSerializer 就可以了。
但是这个jsonSerializer有⼀个⽐较严重的问题,就是这个nullValueSerializer是全局的,即所有的null都会应⽤这个JsonSerializer,在这个类中⽆法判断类型。
所以继续向下跟代码:
跟⼊ ser.serialize(value, jgen, this); 这个⽅法,发现其有许多的实现,通过调试模式,进⼊了⼀个叫做BeanSerializer的类,其实现为:/*** Main serialization method that will delegate actual output to
* configured
* {@linkBeanPropertyWriter} instances.*/
@Overridepublicfinalvoidserialize(Object bean, JsonGenerator jgen, SerializerProvider
provider)throwsIOException, JsonGenerationException
{
if(_objectIdWriter !=null) {
_serializeWithObjectId(bean, jgen, provider,true);return;
}
jgen.writeStartObject();if(_propertyFilterId !=null) {
serializeFieldsFiltered(bean, jgen, provider);
}else{
json值的类型有哪些//调试模式下最终⾛了这个⽅法
serializeFields(bean, jgen, provider);
} jgen.writeEndObject();
}
protected void serializeFields(Object bean, JsonGenerator jgen, SerializerProvider
provider)throwsIOException, JsonGenerationException
{finalBeanPropertyWriter[] props;if(_filteredProps !=null&& ActiveView() !=null) {
props=_filteredProps;
}else{
props=_props;
}inti = 0;try{for(finalintlen = props.length; i < len; ++i) {
BeanPropertyWriter prop=props[i];
if(prop !=null) {//can have nulls in filtered list
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论