fastjson序列化对象后属性变更问题

使用fastjson进行JSON序列化存储到数据库后,发现JSON字符串"莫名其妙地"多了一些属性。

java 复制代码
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;
    }
}

测试

java 复制代码
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);
    }
}

结果

{"active":true,"id":123,"valid":false}

多了一个 active 属性,少了一个isActive属性。

问题出在这个函数

java 复制代码
com.alibaba.fastjson.serializer.SerializeConfig
java 复制代码
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);
}

om.alibaba.fastjson.util.TypeUtils#computeGetters

java 复制代码
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);
}

fastjson通过反射虽然有能力识别真实的属性名,但是实际操作时会根据 getter 方法反推出属性名,造成转为JSON字符串时和实际属性名存在偏差。

解决办法

布尔类型的变量不要加is前缀或者使用fastjson自带的@JSONField注解,不过这种方式fastjson的侵入性太强。

java 复制代码
public class MyClass {

    @JSONField( name="isActive")
    // boolean 类型的属性
    private boolean isActive;
    private boolean valid;

    // 省略其他

}

阿里巴巴java开发手册

Java开发 命名风格_w3cschool

相关推荐
卷毛的技术笔记15 分钟前
告别硬编码!Spring AI Alibaba 实现 AI Agent 智能工具调用(Tool Calling)
java·人工智能·后端·python·spring·ai编程
编程大师哥16 分钟前
匿名函数 lambda + 高阶函数
java·python·算法
isyangli_blog17 分钟前
OpenDayLight (Carbon 版本) 启动与组件安装
开发语言·php
vb20081125 分钟前
FastAPI APIRouter
开发语言·python
Benszen27 分钟前
KVM虚拟化解决方案
开发语言·perl
会编程的土豆28 分钟前
Go 语言反射(Reflection)详解
开发语言·后端·golang
東雪木31 分钟前
多线程与并发编程 专属复习笔记
java·开发语言·笔记·java面试
adrninistrat0r36 分钟前
Java调用链MCP分析工具
java·python·ai编程
杨充1 小时前
1.3 浮点型数据设计灵魂
开发语言·python·算法
噜噜噜阿鲁~1 小时前
python学习笔记 | 11.3、面向对象高级编程-多重继承
java·开发语言