问题形容

public class Demo {    private Boolean isHot;    private Boolean isQuick;    public Boolean getHot() {        return isHot;    }    public void setHot(Boolean hot) {        isHot = hot;    }    public Boolean getQuick() {        return isQuick;    }    public void setQuick(Boolean quick) {        isQuick = quick;    }}

例如下面一个bean,getset办法均为idea主动生成的(Idea 2020.1),Fastjson序列化后的后果为

{    "hot":true,    "quick":true}

咱们其实冀望的是

{    "isHot":true,    "isQuick":true}

解决方案

计划一

批改get办法为getIsXXX
public Boolean getHot() ->public Boolean getIsHot()

计划二

去掉getset办法应用lombok,如果公司容许的话

计划三

批改idea默认模板

#set($paramName = $helper.getParamName($field, $project))#if($field.modifierStatic)static ###end$field.type ###set($name = $StringUtil.capitalizeWithJavaBeanConvention($StringUtil.sanitizeJavaIdentifier($helper.getPropertyName($field, $project))))#if ($field.name == $paramName)get###elsegetIs###end${name}() {return this.##$field.name;}

计划四

不要以is结尾,退出公司的代码标准,《Java开发手册(泰山版)》中也提到了

【强制】POJO 类中的任何布尔类型的变量,都不要加 is 前缀,否则局部框架解析会引起序列 化谬误。

源码剖析

上面咱们看一下Fastjson源码

public static List<FieldInfo> computeGetters(Class<?> clazz, //                                             JSONType jsonType, //                                             Map<String,String> aliasMap, //                                             Map<String,Field> fieldCacheMap, //                                             boolean sorted, //                                             PropertyNamingStrategy propertyNamingStrategy //){    Map<String,FieldInfo> fieldInfoMap = new LinkedHashMap<String,FieldInfo>();    boolean kotlin = TypeUtils.isKotlin(clazz);    // for kotlin    Constructor[] constructors = null;    Annotation[][] paramAnnotationArrays = null;    String[] paramNames = null;    short[] paramNameMapping = null;    Method[] methods = clazz.getMethods();    for(Method method : methods){       .....此处省略                //次要是这里        if(methodName.startsWith("get")){            if(methodName.length() < 4){                continue;            }            if(methodName.equals("getClass")){                continue;            }            if(methodName.equals("getDeclaringClass") && clazz.isEnum()){                continue;            }            char c3 = methodName.charAt(3);            String propertyName;            Field field = null;            if(Character.isUpperCase(c3) //                    || c3 > 512 // for unicode method name                    ){                if(compatibleWithJavaBean){                    //依据get办法取值                    propertyName = decapitalize(methodName.substring(3));                } else{                    propertyName = Character.toLowerCase(methodName.charAt(3)) + methodName.substring(4);                }                propertyName = getPropertyNameByCompatibleFieldName(fieldCacheMap, methodName, propertyName, 3);            }                      ......再度省略            fieldInfoMap.put(propertyName, fieldInfo);        }    }    Field[] fields = clazz.getFields();    computeFields(clazz, aliasMap, propertyNamingStrategy, fieldInfoMap, fields);    return getFieldInfos(clazz, sorted, fieldInfoMap);}

前面就基本上以这个名称为准了。


这个writer是通过动静生成的一个bean,所以代码无奈追踪,然而它强转了下`
return (JavaBeanSerializer) instance;
所以咱们能够看下JavaBeanSerializer::write办法看下是如何把bean转成String的`

    protected void write(JSONSerializer serializer, //                      Object object, //                      Object fieldName, //                      Type fieldType, //                      int features,                      boolean unwrapped    ) throws IOException {        SerializeWriter out = serializer.out;        if (object == null) {            out.writeNull();            return;        }        if (writeReference(serializer, object, features)) {            return;        }        final FieldSerializer[] getters;                //获取咱们刚刚解析的成员变量c h        if (out.sortField) {            getters = this.sortedGetters;        } else {            getters = this.getters;        }        SerialContext parent = serializer.context;        if (!this.beanInfo.beanType.isEnum()) {            serializer.setContext(parent, object, fieldName, this.beanInfo.features, features);        }        final boolean writeAsArray = isWriteAsArray(serializer, features);        FieldSerializer errorFieldSerializer = null;        try {            final char startSeperator = writeAsArray ? '[' : '{';            final char endSeperator = writeAsArray ? ']' : '}';            if (!unwrapped) {                //全程增加到out外面,最初toJSONString输入的也是out                out.append(startSeperator);            }            if (getters.length > 0 && out.isEnabled(SerializerFeature.PrettyFormat)) {                serializer.incrementIndent();                serializer.println();            }            boolean commaFlag = false;            if ((this.beanInfo.features & SerializerFeature.WriteClassName.mask) != 0                ||(features & SerializerFeature.WriteClassName.mask) != 0                || serializer.isWriteClassName(fieldType, object)) {                Class<?> objClass = object.getClass();                final Type type;                if (objClass != fieldType && fieldType instanceof WildcardType) {                    type = TypeUtils.getClass(fieldType);                } else {                    type = fieldType;                }                if (objClass != type) {                    writeClassName(serializer, beanInfo.typeKey, object);                    commaFlag = true;                }            }            char seperator = commaFlag ? ',' : '\0';            final boolean writeClassName = out.isEnabled(SerializerFeature.WriteClassName);            char newSeperator = this.writeBefore(serializer, object, seperator);            commaFlag = newSeperator == ',';            final boolean skipTransient = out.isEnabled(SerializerFeature.SkipTransientField);            final boolean ignoreNonFieldGetter = out.isEnabled(SerializerFeature.IgnoreNonFieldGetter);            for (int i = 0; i < getters.length; ++i) {                              .....字符串拼接                           }            this.writeAfter(serializer, object, commaFlag ? ',' : '\0');            if (getters.length > 0 && out.isEnabled(SerializerFeature.PrettyFormat)) {                serializer.decrementIdent();                serializer.println();            }            if (!unwrapped) {                //全程增加进out外面                out.append(endSeperator);            }        } catch (Exception e) {            .....解决异样,疏忽        } finally {            serializer.context = parent;        }    }