问题形容
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; } }