记一次Integer序列化一直为0,不能为空

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代码框架代码的问题,以后都可以采用类似的方法进行定位。
 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值