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

相关推荐
SL_staff17 分钟前
运维救火实战:钉钉API变更致薪资计算中断,如何用可视化逻辑引擎5分钟热修复
java·开源·全栈
低调滴开发17 分钟前
3 行代码写崩一个函数?切片才是 Rust 字符串处理的正确姿势
开发语言·后端·rust
CodeYp201926 分钟前
第15讲:二叉搜索树
开发语言·c++·二叉搜索树
猫猫.15339 分钟前
HashTable、HashMap、ConcurrentHashMap 核心区别总结
java·开发语言·java-ee
郭小李1 小时前
spring mvc 工作流程
java·spring·mvc
SL_staff2 小时前
BI大屏嵌入MES的登录态难题:JVS统一账号体系实战解法
java·数据分析·数据可视化
乌暮2 小时前
综合案例:宠物电商系统
java·开发语言·spring·mvc·restful·1024程序员节
大文说跨境2 小时前
亚马逊多店铺的图片素材怎么批量去重:EXIF 与哈希的处理流程
开发语言·php
VimorphTech2 小时前
一段字幕太长,怎样拆句并安排显示时间?
java·spring boot
万联WANFLOW2 小时前
Kimi K3.1 Pro 接口接入指南:模型选型、费用计算与零数据保留
java·spring boot·python·安全·spring·大模型