A colleague said that after using fastjson for JSON serialization and storing in the database, he found that the JSON string "inexplicably" had some more attributes! After looking at the code for help, I saw the properties of the basic type of boolean type starting with is, and then I saw fastjson, and I wanted to laugh.
recurrent
defineMyClass
public class MyClass {
// boolean 类型的属性
private boolean isActive;
private boolean valid;
// int 类型的属性
private int id;
// 默认构造器
public MyClass() {
}
// 带有所有属性的构造器
public MyClass(boolean isActive, boolean valid, int id) {
this.isActive = isActive;
this.valid = valid;
this.id = id;
}
// isActive 的 getter 和 setter 方法
public boolean isActive() {
return isActive;
}
public void setActive(boolean isActive) {
this.isActive = isActive;
}
// valid 的 getter 和 setter 方法
public boolean getValid() {
return valid;
}
public void setValid(boolean valid) {
this.valid = valid;
}
// id 的 getter 和 setter 方法
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
Write the test code:
import com.alibaba.fastjson.JSON;
public class MyClassMain {
public static void main(String[] args) {
// 创建 MyClass 对象
MyClass myClass = new MyClass(true, false, 123);
// 使用 fastjson 序列化对象
String jsonString = JSON.toJSONString(myClass);
// 打印 JSON 字符串
System.out.println(jsonString);
}
}
result:
{“active”:true,“id”:123,“valid”:false}
We found that there is one more active attribute and one less isActive attribute!
Recommend an open source and free Spring Boot practical project:
analyze
Through debugging, it can be found that the problem occurs in the following function:
com.alibaba.fastjson.serializer.SerializeConfig#createJavaBeanSerializer(java.lang.Class<?>)
public final ObjectSerializer createJavaBeanSerializer(Class<?> clazz) {
String className = clazz.getName();
long hashCode64 = TypeUtils.fnv1a_64(className);
if (Arrays.binarySearch(denyClasses, hashCode64) >= 0) {
throw new JSONException("not support class : " + className);
}
// 关键
SerializeBeanInfo beanInfo = TypeUtils.buildBeanInfo(clazz, null, propertyNamingStrategy, fieldBased);
if (beanInfo.fields.length == 0 && Iterable.class.isAssignableFrom(clazz)) {
return MiscCodec.instance;
}
return createJavaBeanSerializer(beanInfo);
}
And the key to buildBeanInfo iscom.alibaba.fastjson.util.TypeUtils#computeGetters
public static List<FieldInfo> computeGetters(Class<?> clazz, //
JSONType jsonType, //
Map<String,String> aliasMap, //
Map<String,Field> fieldCacheMap, //
boolean sorted, //
PropertyNamingStrategy propertyNamingStrategy //
){
// 省略部分代码
if(methodName.startsWith("is")){
if(methodName.length() < 3){
continue;
}
if(returnType != Boolean.TYPE
&& returnType != Boolean.class){
continue;
}
char c2 = methodName.charAt(2);
String propertyName;
Field field = null;
if(Character.isUpperCase(c2)){
if(compatibleWithJavaBean){
propertyName = decapitalize(methodName.substring(2));
} else{
propertyName = Character.toLowerCase(methodName.charAt(2)) + methodName.substring(3);
}
// 这里 isActive 的属性名被计算出 active
propertyName = getPropertyNameByCompatibleFieldName(fieldCacheMap, methodName, propertyName, 2);
}
// 省略其他
JSONField fieldAnnotation = null;
if(field != null){
fieldAnnotation = TypeUtils.getAnnotation(field, JSONField.class);
if(fieldAnnotation != null){
if(!fieldAnnotation.serialize()){
continue;
}
ordinal = fieldAnnotation.ordinal();
serialzeFeatures = SerializerFeature.of(fieldAnnotation.serialzeFeatures());
parserFeatures = Feature.of(fieldAnnotation.parseFeatures());
if(fieldAnnotation.name().length() != 0){
//关键: 使用 JSONField 注解设置的 name 替代属性名
propertyName = fieldAnnotation.name();
if(aliasMap != null){
propertyName = aliasMap.get(propertyName);
if(propertyName == null){
continue;
}
}
}
if(fieldAnnotation.label().length() != 0){
label = fieldAnnotation.label();
}
}
}
// 省略部分代码
FieldInfo fieldInfo = new FieldInfo(propertyName, method, field, clazz, null, ordinal, serialzeFeatures, parserFeatures,
annotation, fieldAnnotation, label);
fieldInfoMap.put(propertyName, fieldInfo);
}
}
Field[] fields = clazz.getFields();
computeFields(clazz, aliasMap, propertyNamingStrategy, fieldInfoMap, fields);
return getFieldInfos(clazz, sorted, fieldInfoMap);
}
In fact, although fastjson has the ability to identify the real attribute name through reflection, it will deduce the attribute name according to the getter method in actual operation, resulting in a deviation from the actual attribute name when converted into a JSON string.
Solution
Follow the Alibaba Java Development Manual
Teacher Gu Jin's "Java Development Manual" specifically emphasizes that any Boolean variable should not be prefixed with is. When the basic type Boolean attribute is reversed, it will be mistaken that the attribute cannot be obtained without is, and an exception will be thrown. Pay attention to the official account: Java core technology, reply: manual, you can get the full HD version.
use an alias
Use the @JSONField annotation that comes with fastjson, but fastjson is too intrusive in this way.
public class MyClass {
@JSONField( name="isActive")
// boolean 类型的属性
private boolean isActive;
private boolean valid;
// 省略其他
}
Summarize
I think that for Java programmers, "Alibaba Java Development Manual" should be read at least 3 times. Too many common low-level problems found in the work are problems that already exist in the "Alibaba Java Development Manual". Pay attention to the official account: Java core technology, reply: manual, you can get the full HD version.
However, although the "Alibaba Java Development Manual" is recommended many times, although it is very thin, many people still don't read it carefully several times, resulting in falling down many times in the same place. Even if you encounter a similar problem, it is easy to quickly figure out the reason.
When we encounter a problem, we must not stop at solving the problem, but should look for the most reasonable solution. For example, although adding @JSONField
can "solve the problem", it is too intrusive. If other people use this object to use other JSON serialization tools, problems will arise. This is not a good solution.
In the age of AI, if you encounter a problem and cannot solve it quickly, you can consider seeking help from AI. But when using AI, be sure to explain the problem clearly. Many students asked questions that even other colleagues could not understand, let alone AI.
Copyright statement: This article is an original article by CSDN blogger "Mingming Ruyue Senior", and follows the CC 4.0 BY-SA copyright agreement. For reprinting, please attach the original source link and this statement. Original link: https://blog.csdn.net/w605283073/article/details/131270338
Recent hot article recommendation:
1. 1,000+ Java interview questions and answers (2022 latest version)
2. Brilliant! Java coroutines are coming. . .
3. Spring Boot 2.x tutorial, too comprehensive!
5. The latest release of "Java Development Manual (Songshan Edition)", download quickly!
Feel good, don't forget to like + forward!