测试用例:
public class FastJsonBug {
public static void main(String[] args) {
String s = "{ \"componentKey\" : \"CMDB_UPDATE_SERVER\"}";
Step step = JSON.parseObject(s, Step.class);
System.out.println(step.getComponentKey());
}
@Data
private static class Step {
@JSONField(name = "component_key")
private String componentKey;
}
}
以上代码打印出来的结果是null 现象:加了JSONField注解的字段在反序列化过程中无法准确反序列化 原因:1.2.71以上版本版本中智能匹配时字段hash的获取方式为以下代码
if (this.smartMatchHashArray == null) {
long[] hashArray = new long[sortedFieldDeserializers.length];
for (int i = 0; i < sortedFieldDeserializers.length; i++) {
//获取了已经计算好的nameHashCode
hashArray[i] = sortedFieldDeserializers[i].fieldInfo.nameHashCode;
}
Arrays.sort(hashArray);
this.smartMatchHashArray = hashArray;
}
//使用计算好的nameHashCode和json字段的hash做匹配
// smartMatchHashArrayMapping
long smartKeyHash = TypeUtils.fnv1a_64_extract(key);
int pos = Arrays.binarySearch(smartMatchHashArray, smartKeyHash);
if (pos < 0) {
long smartKeyHash1 = TypeUtils.fnv1a_64_lower(key);
pos = Arrays.binarySearch(smartMatchHashArray, smartKeyHash1);
}
而已经计算好的nameHashCode是这样计算的在FieldInfo类中
private long nameHashCode64(String name, JSONField annotation)
{
if (annotation != null && annotation.name().length() != 0) {
return TypeUtils.fnv1a_64_extract(name);
}
return TypeUtils.fnv1a_64_lower(name);
}
当字段上存在JSONField注解时nameHashCode都是从fnv1a_64_extract计算的hash,这种计算hash的方式是带着下划线和中划线的,当我们json字段为驼峰时就会计算出来的hash匹配不上
---------------------------------------分割线----------------------------------------------- 以下为1.2.70版本的实现: 匹配字段hash:
long smartKeyHash = TypeUtils.fnv1a_64_lower(key);
if (this.smartMatchHashArray == null) {
long[] hashArray = new long[sortedFieldDeserializers.length];
for (int i = 0; i < sortedFieldDeserializers.length; i++) {
hashArray[i] = TypeUtils.fnv1a_64_lower(sortedFieldDeserializers[i].fieldInfo.name);
}
Arrays.sort(hashArray);
this.smartMatchHashArray = hashArray;
}
// smartMatchHashArrayMapping
int pos = Arrays.binarySearch(smartMatchHashArray, smartKeyHash);
boolean is = false;
if (pos < 0 && (is = key.startsWith("is"))) {
smartKeyHash = TypeUtils.fnv1a_64_lower(key.substring(2));
pos = Arrays.binarySearch(smartMatchHashArray, smartKeyHash);
}
可以看到在1.2.70版本以下 每次都会使用fnv1a_64_lower这种方式计算hash则可以匹配上
希望大大们可以解决一下这个问题