• fastjson与lombok一起用出现序列化问题


    文章内部信息已脱敏

    有一次在测试环境调用网易电子签章平台的接口,用来生成印章图片。

    首先用postman去测试接口,除了必传的固定请求头,请求体参数如下:

    {
        "userId": "***********",
        "templateType": "STAR",
        "color": "RED",
        "hText": "合同专用章",
        "qText": "2023-01-17"   
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    返回的结果是印章图片的base64。转化为图片后是。
    在这里插入图片描述

    然后在java项目里去调用该接口,用了feign去调第三方平台接口。

    但是发现返回的base64转化为图片后,始终是如下图,也就是传入的参数中hText(横向文)与qText(下旋文),这两个字段没有生效。

    在这里插入图片描述

    代码中的对象属性定义为:

    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    @Data
    @Accessors(chain = true)
    public class EsignAddSealDTO {
    
        private String userId;
    
        private String templateType;
    
        private String color;
    
        private String hText;
    
        private String qText;
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    仔细检查了代码,发现对象属性之类的代码并没有问题,那为什么这两个字段会没有生效呢?

    由于postman接口可以返回正确的结果,并且java项目调用中也有返回,可以定位到还是传参对象出了问题。

    EsignAddSealDTO req = EsignAddSealDTO.builder().userId("*************").templateType("STAR").color("RED")
            .hText("合同专用章").qText("2023-01-17").build();
    System.out.println(JSONObject.toJSONString(req));
    
    • 1
    • 2
    • 3

    打印传参对象的json字符串,发现结果为:

    {"HText":"合同专用章","QText":"2023-01-17","color":"RED","templateType":"STAR","userId":"*************"}
    
    • 1

    !! 序列化的json库采用的是fastjson,序列化后的json字符串中hText和qText竟然属性名首字母变为了大写。怪不得这两个字段没有生效。

    项目中的fastjson版本是2.0.9。

    看一下原因,首先,使用了lombok的@Data注解之后,默认生成的hText属性的get方法名变为了getHText(), qText属性的get方法名变为了getQText()。

    而在fastjson中,获取属性名的方法是com.alibaba.fastjson2.util.BeanUtils#getterName。
    源码debug如下:

    其中mthodName入参为“getQText”,namingStrategy传参为null, 方法中修改设值为“CamelCase”。
    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    这边可以看到源码中,对于get开头的方法名,如getQText,首先取get后的字符串为chars, 这里chars就是[Q, T, e, x, t]。

    chars首字母为Q, 这时候做判断,如果第二个字符为大写,则直接返回chars为属性名;如果第二个字符为小写,则将首字母变为小写,再返回。这里由于第二个字符为T,因此这里直接返回QText为属性名。

    再举例:如果方法名是getUserId,取chars为[U, s, e, r, I, d], 取首字母为U,因为第二个字符为小写,因此将首字母变为小写,返回userId为属性名。

    因此getQText方法得到的属性名就是QText。而不是类定义的属性名qText。

    知道原因后,就简单了,可以不使用lombok,而是直接生成get/set方法,

    public String gethText() {
        return hText;
    }
    
    public void sethText(String hText) {
        this.hText = hText;
    }
    
    public String getqText() {
        return qText;
    }
    
    public void setqText(String qText) {
        this.qText = qText;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    就可以返回正确属性名了。

    注意:

    使用@Data注解,即使在属性hText、qText上加上@JsonProperty注解,依旧不起作用。但是加在其他属性上时生效的,如在color上加注解,可以修改序列化后的属性名。

    @Data
    @Builder
    public class EsignAddSealDTO {
    
        private String userId;
    
        private String templateType;
    
        @JsonProperty(value = "COLOR")
        private String color;
    
        @JsonProperty(value = "hText")
        private String hText;
    
        @JsonProperty(value = "qText")
        private String qText;
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    生成的序列化json字符串为:

    {"COLOR":"RED","HText":"合同专用章","QText":"2023-01-17","templateType":"STAR","userId":"*************"}
    
    • 1

    附录: 浏览源码顺序:
    com.alibaba.fastjson.JSON#toJSONString(java.lang.Object)
    com.alibaba.fastjson2.JSONWriter.Context#getObjectWriter(java.lang.reflect.Type,java.lang.Class)
    com.alibaba.fastjson2.writer.ObjectWriterProvider#getObjectWriter(java.lang.reflect.Type,
    java.lang.Class, boolean)
    com.alibaba.fastjson2.writer.ObjectWriterCreatorASM#createObjectWriter
    com.alibaba.fastjson2.util.BeanUtils#getterName

  • 相关阅读:
    为什么做生意可以让双方生活的更好?
    前端面试题---作用域链和原型链
    Django ORM
    CVE-2021-35042
    《c++程序设计》谭浩强课后习题答案 第三章
    Redux 中的函数概念
    arm裸机测试led灯亮灭、风扇、马达等
    06 redis 集群搭建
    线程,互斥锁,临界区
    【Unity】万人同屏高级篇, BRG & Jobs实战应用, 海量物体同屏
  • 原文地址:https://blog.csdn.net/weixin_42120561/article/details/130913971