当前位置: 首页 > news >正文

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

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


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;}
}

测试 


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属性。

问题出在这个函数

com.alibaba.fastjson.serializer.SerializeConfig
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

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 的属性名被计算出 activepropertyName = 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的侵入性太强。

public class MyClass {@JSONField( name="isActive")// boolean 类型的属性private boolean isActive;private boolean valid;// 省略其他}

阿里巴巴java开发手册

Java开发 命名风格_w3cschool

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • SQL Chat:从SQL到SPEAKL的数据库操作新纪元
  • 战略引领下的成功产品开发之路
  • Tomcat源码解析(八):一个请求的执行流程(附Tomcat整体总结)
  • MATLAB 论文绘图规范标注
  • 地理信息系统(ArcGIS)在水文水资源、水环境中的实践技术应用及案例分析教程
  • 减少GPU显存的策略
  • 视觉SLAM十四讲:从理论到实践(Chapter8:视觉里程计2)
  • 公有云服务器部署springboot工程详细步骤
  • QT 和VS 针对linux开发的不同
  • 41 mysql subquery 的实现
  • GNU/Linux - 使用字符设备来操作GPIO
  • Redis与缓存失效策略:实现高效的数据过期处理
  • 13. ESP32-HTTPClient(Arduino)
  • 从零实现ChatGPT:第三章实现大型语言模型(1)
  • HTML静态网页成品作业(HTML+CSS)—— 名人霍金介绍网页(6个页面)
  • 【RocksDB】TransactionDB源码分析
  • CSS实用技巧干货
  • docker容器内的网络抓包
  • express.js的介绍及使用
  • Hibernate【inverse和cascade属性】知识要点
  • HTTP中的ETag在移动客户端的应用
  • Java 网络编程(2):UDP 的使用
  • Java知识点总结(JDBC-连接步骤及CRUD)
  • macOS 中 shell 创建文件夹及文件并 VS Code 打开
  • MySQL-事务管理(基础)
  • vue+element后台管理系统,从后端获取路由表,并正常渲染
  • vue数据传递--我有特殊的实现技巧
  • 分享一份非常强势的Android面试题
  • 构建工具 - 收藏集 - 掘金
  • 漫谈开发设计中的一些“原则”及“设计哲学”
  • 一个SAP顾问在美国的这些年
  • 中文输入法与React文本输入框的问题与解决方案
  • 阿里云重庆大学大数据训练营落地分享
  • ​Base64转换成图片,android studio build乱码,找不到okio.ByteString接腾讯人脸识别
  • ​sqlite3 --- SQLite 数据库 DB-API 2.0 接口模块​
  • # include “ “ 和 # include < >两者的区别
  • #VERDI# 关于如何查看FSM状态机的方法
  • #微信小程序(布局、渲染层基础知识)
  • #微信小程序:微信小程序常见的配置传旨
  • #我与Java虚拟机的故事#连载13:有这本书就够了
  • (2024.6.23)最新版MAVEN的安装和配置教程(超详细)
  • (python)数据结构---字典
  • (八)光盘的挂载与解挂、挂载CentOS镜像、rpm安装软件详细学习笔记
  • (附源码)springboot社区居家养老互助服务管理平台 毕业设计 062027
  • (四)c52学习之旅-流水LED灯
  • (转)C#调用WebService 基础
  • (转)nsfocus-绿盟科技笔试题目
  • (转)利用PHP的debug_backtrace函数,实现PHP文件权限管理、动态加载 【反射】...
  • (转)全文检索技术学习(三)——Lucene支持中文分词
  • (转载)微软数据挖掘算法:Microsoft 时序算法(5)
  • ****Linux下Mysql的安装和配置
  • ***linux下安装xampp,XAMPP目录结构(阿里云安装xampp)
  • ./configure、make、make install 命令
  • .java 9 找不到符号_java找不到符号
  • .net framework profiles /.net framework 配置