package com.cn.hnust.pojo;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.io.Serializable;
/**
* @Author: dainan
* @Date: 2018/12/20 16:21
* @Description:
*/
public class RR implements Serializable {
/**
* 是否选择商户区域(1/0)
*/
private boolean storeAreas;
/**
* 客户端GPS定位区域(1/0)
*/
@JsonProperty(value = "GPSAreas")
private boolean GPSAreas;
/**
* 反序列化为null
*/
private Integer value = -1;
private int valueInt;
public int getValueInt() {
return valueInt;
}
public void setValueInt(int valueInt) {
this.valueInt = valueInt;
}
public Integer getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public boolean isStoreAreas() {
return storeAreas;
}
public void setStoreAreas(boolean storeAreas) {
this.storeAreas = storeAreas;
}
public boolean isGPSAreas() {
return GPSAreas;
}
public void setGPSAreas(boolean GPSAreas) {
this.GPSAreas = GPSAreas;
}
@JsonProperty(value = "Name")
private String Name;
public String getName() {
return Name;
}
public void setName(String name) {
this.Name = name;
}
}
随意建一个类,建立一个main函数
public static void main(String[] args) {
String zz = "";
ObjectMapper objectMapper = new ObjectMapper();
try {
zz = objectMapper.writeValueAsString(new RR());
} catch (JsonProcessingException e) {
e.printStackTrace();
}
System.out.println(zz);
String pp = "{\"storeAreas\":false,\"value\":\"\",\"valueInt\":\"\",\"name\":null,\"gpsareas\":false,\"GPSAreas\":false,\"Name\":null}";
ObjectMapper mapper = new ObjectMapper();
RR searchCondition = null;
try {
searchCondition = mapper.readValue(pp, RR.class);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(searchCondition);
}
其序列化结果为:value值一直为0.
其原因是:
public void setValue(int value) { this.value = value; }
value在set函数中为int基本属性,Integer在拆箱时候,将默认值为0
然后我查看源码获得如下结果:
第一层进入:readWithMessageConverters @Override public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { Object arg = readWithMessageConverters(webRequest, parameter, parameter.getGenericParameterType()); String name = Conventions.getVariableNameForParameter(parameter); WebDataBinder binder = binderFactory.createBinder(webRequest, arg, name); if (arg != null) { validateIfApplicable(binder, parameter); if (binder.getBindingResult().hasErrors() && isBindExceptionRequired(binder, parameter)) { throw new MethodArgumentNotValidException(parameter, binder.getBindingResult()); } } mavContainer.addAttribute(BindingResult.MODEL_KEY_PREFIX + name, binder.getBindingResult()); return arg; }
接着进入函数:readWithMessageConverters,其中Body就是我们反序列化的对象。进入readJavaType函数
if (converter instanceof GenericHttpMessageConverter) { GenericHttpMessageConverter<?> genericConverter = (GenericHttpMessageConverter<?>) converter; if (genericConverter.canRead(targetType, contextClass, contentType)) { if (logger.isDebugEnabled()) { logger.debug("Read [" + targetType + "] as \"" + contentType + "\" with [" + converter + "]"); } if (inputMessage.getBody() != null) { inputMessage = getAdvice().beforeBodyRead(inputMessage, param, targetType, converterType); body = genericConverter.read(targetType, contextClass, inputMessage); body = getAdvice().afterBodyRead(body, inputMessage, param, targetType, converterType); } else { body = null; body = getAdvice().handleEmptyBody(body, inputMessage, param, targetType, converterType); } break; } } else if (targetClass != null) { if (converter.canRead(targetClass, contentType)) { if (logger.isDebugEnabled()) { logger.debug("Read [" + targetType + "] as \"" + contentType + "\" with [" + converter + "]"); } if (inputMessage.getBody() != null) { inputMessage = getAdvice().beforeBodyRead(inputMessage, param, targetType, converterType); body = ((HttpMessageConverter<T>) converter).read(targetClass, inputMessage); body = getAdvice().afterBodyRead(body, inputMessage, param, targetType, converterType); } else { body = null; body = getAdvice().handleEmptyBody(body, inputMessage, param, targetType, converterType); } break; } }
第三步:在readType函数中采用的是_readMapAndClose进行序列化,其result是序列化对象,进入deser.deserialize(jp, ctxt);函数
protected Object _readMapAndClose(JsonParser jp, JavaType valueType) throws IOException, JsonParseException, JsonMappingException { try { Object result; JsonToken t = _initForReading(jp); if (t == JsonToken.VALUE_NULL) { // [JACKSON-643]: Ask JsonDeserializer what 'null value' to use: DeserializationContext ctxt = createDeserializationContext(jp, getDeserializationConfig()); result = _findRootDeserializer(ctxt, valueType).getNullValue(); } else if (t == JsonToken.END_ARRAY || t == JsonToken.END_OBJECT) { result = null; } else { DeserializationConfig cfg = getDeserializationConfig(); DeserializationContext ctxt = createDeserializationContext(jp, cfg); JsonDeserializer<Object> deser = _findRootDeserializer(ctxt, valueType); if (cfg.useRootWrapping()) { result = _unwrapAndDeserialize(jp, ctxt, cfg, valueType, deser); } else { result = deser.deserialize(jp, ctxt); } ctxt.checkUnresolvedObjectId(); } // Need to consume the token too jp.clearCurrentToken(); return result; } finally { try { jp.close(); } catch (IOException ioe) { } } }
第4部,如下,可知道deserializeFromObject函数才是真真正正的反序列化
public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { JsonToken t = p.getCurrentToken(); // common case first if (t == JsonToken.START_OBJECT) { // TODO: in 2.6, use 'p.hasTokenId()' if (_vanillaProcessing) { return vanillaDeserialize(p, ctxt, p.nextToken()); } p.nextToken(); if (_objectIdReader != null) { return deserializeWithObjectId(p, ctxt); } return deserializeFromObject(p, ctxt); } return _deserializeOther(p, ctxt, t); }
第五步,在函数中可以看到 _valueInstantiator.createUsingDefault(ctxt);是反序列化的执行者
final Object bean = _valueInstantiator.createUsingDefault(ctxt); // [databind#631]: Assign current value, to be accessible by custom deserializers p.setCurrentValue(bean); if (p.canReadObjectId()) { Object id = p.getObjectId(); if (id != null) { _handleTypedObjectId(p, ctxt, bean, id); } } if (_injectables != null) { injectValues(ctxt, bean); } if (_needViewProcesing) { Class<?> view = ctxt.getActiveView(); if (view != null) { return deserializeWithView(p, ctxt, bean, view); } } JsonToken t = p.getCurrentToken(); for (; t == JsonToken.FIELD_NAME; t = p.nextToken()) { String propName = p.getCurrentName(); p.nextToken(); if (!_beanProperties.findDeserializeAndSet(p, ctxt, bean, propName)) { handleUnknownVanilla(p, ctxt, bean, propName); } }
第六部,进入函数发现,createUsingDefault(ctxt)仅仅是创建对象,对象的赋值不是它执行,继续往下走发现,以下代码
JsonToken t = p.getCurrentToken(); for (; t == JsonToken.FIELD_NAME; t = p.nextToken()) { String propName = p.getCurrentName(); p.nextToken(); if (!_beanProperties.findDeserializeAndSet(p, ctxt, bean, propName)) { handleUnknownVanilla(p, ctxt, bean, propName); } }
进入赋值函数deserializeAndSet中,可以看到_setter.invoke(instance, value);
protected final transient Method _setter;代表类中所有的setter方法
@Override public void deserializeAndSet(JsonParser jp, DeserializationContext ctxt, Object instance) throws IOException { Object value = deserialize(jp, ctxt); try { _setter.invoke(instance, value); } catch (Exception e) { _throwAsIOE(e, value); } }
谜题也揭开了在调用
public void setValue(int value) {
this.value = value;
}这个方法中,int的初始值为0,所以其序列化出的结果也为0.
这是一次经典的源码定位分析问题,对于小白的程序员我来说,是一次宝贵的经验。对于Java代码框架代码的问题,以后都可以采用类似的方法进行定位。