fastjosn在低版本丢字段问题

简单的说:
对于java bean中有字段类似pId这种写法,特征是第一个字母小写,第二个字母大写,在eclipse中生成的getter setter方法是 getpId, setpId。
在低版本的fastjson,比如1.1.41中将java bean序列化成json字符串的时候,会丢掉pId这个字段。 使用高版本,比如1.2.46,就不会有这个问题。
那么,这到底是谁的锅?
先说结论,fastjson的锅。
先说,eclipse生成的对不对?生成的是对的,参见这里

This is not the problem of eclipse it is the logic of getter and setter.

再说eclipse为什么要这么生成?因为符合java bean规范
简单地说,getter setter方法是读取java bean字段的入口。 如果生成的是getPId和setPId,通过getter setter 方法拿到的属性字段名将是PId,不会是pId。为了能通过getter setter方法拿到的字段是pId,所以倒推出getter setter方法应该是getpId和setpId,参见这里

So when you have the introspection of a class that contains Long getRPersonId() and setRPersonId(Long), a property can be extracted from it. The name of the property generally follows from lower-casing the first letter, and keeping the rest unchanged. But this is not always the case, the exact rule is in paragraph 8.8:

在高版本的fastjson中,不论写的是getpId还是getPId都不会丢字段。

fastjson在1.1.41版本中有问题的获取代码如下:

if (Character.isUpperCase(c3)) {
    if (compatibleWithJavaBean) {
        propertyName = Introspector.decapitalize(methodName.substring(3));
    } else {
        propertyName = Character.toLowerCase(methodName.charAt(3)) + methodName.substring(4);
    }
} else if (c3 == '_') {
    propertyName = methodName.substring(4);
} else if (c3 == 'f') {
    propertyName = methodName.substring(3);
} else {
    continue;
}

fastjson在1.1.42版本中已经修复。
1.1.42的com.alibaba.fastjson.util.TypeUtils.computeGetters(Class<?>, Map<String, String>, boolean)

if (Character.isUpperCase(c3)) {
    if (compatibleWithJavaBean) {
        propertyName = decapitalize(methodName.substring(3));
    } else {
        propertyName = Character.toLowerCase(methodName.charAt(3)) + methodName.substring(4);
    }
} else if (c3 == '_') {
    propertyName = methodName.substring(4);
} else if (c3 == 'f') {
    propertyName = methodName.substring(3);
} else if (methodName.length()>=5 && Character.isUpperCase(methodName.charAt(4))){
    propertyName = decapitalize(methodName.substring(3));
}

fastjson在1.2.46实现如下:
com.alibaba.fastjson.util.TypeUtils.buildBeanInfo(Class<?>, Map<String, String>, PropertyNamingStrategy, boolean)

 List<FieldInfo> fieldInfoList = fieldBased
    ? computeGettersWithFieldBase(beanType, aliasMap, false, propertyNamingStrategy) //
    : computeGetters(beanType, jsonType, aliasMap, fieldCacheMap, false, propertyNamingStrategy);

已经有基于field还是基于getter setter来解析了。

原文地址:https://www.cnblogs.com/simoncook/p/10894003.html