Problem description

public class Demo {
    private Boolean isHot;
    private Boolean isQuick;

    public Boolean getHot(a) {
        return isHot;
    }

    public void setHot(Boolean hot) {
        isHot = hot;
    }

    public Boolean getQuick(a) {
        return isQuick;
    }

    public void setQuick(Boolean quick) { isQuick = quick; }}Copy the code

For example, for the bean above, the getSet method is automatically generated by idea (idea 2020.1), and the Fastjson serialized result is

{
    "hot":true."quick":true
}
Copy the code

What we actually expect is

{
    "isHot":true."isQuick":true
}
Copy the code

The solution

Plan a

Public Boolean getHot() ->public Boolean getIsHot()

Scheme 2

Remove the getSet method and use Lombok, if the company allows it

Plan 3

Example Modify the default IDEA template

#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##
#else
getIs##
#end
${name}() {
return this.##
$field.name;
}
Copy the code

Plan 4

Don’t start with “is.” Add to the company’s code specification, which is also mentioned in the Java Development Manual (Tarzan edition)

[Mandatory] Do not prefix any POJO class variables of Boolean type with is, otherwise part of the framework parsing will cause serialization errors.

Source code analysis

Let’s take a look at the Fastjson source code

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){ ..... Is omitted// The main thing is here
        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){
                    // Value according to the get method
                    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);
}
Copy the code

Basically, this name will prevail.

The writer is dynamically generated by a bean, so the code can’t trace it, but it’s overriddenreturn (JavaBeanSerializer) instance;So we can look at itJavaBeanSerializer::writeHow do we do itbeanintoA String of

    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;
				// Get the member variable c h that we just parsed
        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) {// Add the entire toJSONString to out, and the toJSONString output is also 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 && fieldTypeinstanceof 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) { ..... String concatenation}this.writeAfter(serializer, object, commaFlag ? ', ' : '\ 0');

            if (getters.length > 0 && out.isEnabled(SerializerFeature.PrettyFormat)) {
                serializer.decrementIdent();
                serializer.println();
            }

            if(! unwrapped) {// Add the whole process to outout.append(endSeperator); }}catch(Exception e) { ..... Handle exceptions, ignore}finally{ serializer.context = parent; }}Copy the code