80337960 2019-06-29
将Message对象序列化后,反序列化失败。

response是序列化的结果,start为true,end为false。
message是反序列化后的对象,start和end都为false。
经过自己的初步debug后,并没有任何的头绪,所以google了一下网上的解决办法。
因为content正确反序列化了,所以认为是boolean的问题,就去查关于反序列化布尔值的文章。
然而大面积都是类似下面这种标题的文章:

好像跟我的问题有点不同,但是还是抱着借鉴的心态看了几篇。结果如预期,并没有什么用。但是从其中一片发现boolean和boolean在反序列化时的处理有点不同。所以开始进行尝试。

这是一开始我实体中的字段设置,start和end都是基本类型。
然后将他们改成封装类型boolean,再来看一下结果:

start和end变成了null,依然失败。
然后官方也提到了,boolean默认为false,而boolean默认为null。也就是说,引起上面问题的原因是在反序列化的时候,start和end两个属性没有值。
又查了几篇相关的文章后,依然没有解决问题。所以想干脆使用String算了,进行字符传递。


然而,依然失败。但是既然同样是String类型的,content能够成功反序列化,为什么start和end就不行呢?
然后就开始了找不同。发现了问题的所在。

这里我写了一个自己的构造函数,但是参数只有content,而没有另外的参数。
找到了不同之后,问题就好解决了。在构造函数上填上另外两个属性就好了。
public Message(String content, String start, String end) {
this.content = content;
this.start = start;
this.end = end;
}
成功反序列化!然后在将字段换回boolean类型:

问题成功解决!
从上面我们可以猜测到,fastjson在反序列化的时候,与构造函数是有关的,但是具体的关系,我们还不清楚。所以继续学习一下。
这里我们再添加一个构造函数,构造函数的参数只有两个:
public Message(String content, Boolean start, Boolean end) {
System.out.println("三个参数的构造函数");
this.content = content;
this.start = start;
this.end = end;
}
public Message(String content, Boolean start) {
System.out.println("两个参数的构造函数");
this.content = content;
this.start = start;
}然后我们调用的是三个参数的构造函数:

再用两个和一个参数的构造函数测试:
public Message(String content, Boolean start) {
System.out.println("两个参数的构造函数");
this.content = content;
this.start = start;
}
public Message(Boolean start) {
System.out.println("一个参数的构造函数");
this.start = start;
}
所以从这里看,反序列化会选择参数较多的构造函数。
然后再添加一个无参的构造函数:
public Message(String content, Boolean start, Boolean end) {
System.out.println("三个参数的构造函数");
this.content = content;
this.start = start;
this.end = end;
}
public Message() {
System.out.println("无参构造");
}
然后有无参数的构造函数的时候,会直接调用无参的构造函数。
综上:
1.当没有无参的构造函数时,调用参数较多的构造函数
2.当有无参构造函数时,调用无参构造函数
所以:我们在涉及反序列化的时候,直接先写一个无参构造函数。
有时候我们最开始认为的问题,并不是真正的问题所在,但是这并不能影响我们解决问题。按着步骤一步一步走,就会帮我们排除问题,最终慢慢找到问题所在。
spring-data-redis RedisTemplate 操作redis时发现存储在redis中的key不是设置的string值,前面还多出了许多类似\xac\xed\x00\x05t\x00;