lombok 1.6.22 com.alibaba.fastjson.JSONException: default constructor not found. 若使用 fastjson 要谨慎升级

lombok 1.6.22 版本是唯一会额外生成私有构造函数版本,升级时需要留意是否有地方用到,比如 fastjson !!

问题

先说问题,突然线上报错:

com.alibaba.fastjson.JSONException: default constructor not found.

样例类:

@Data
@Builder
public class User {

    private String name;

    private int age;

}

what ? 怎么好端端的,没有构造方法了?用了 lombok 注解,自测没问题,很诡异。想到最近升级过 lombok 版本,由 ,所以可能于此有关。

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.22</version>
    <!--<version>1.16.22</version> 之前的版本-->
</dependency>
结论

这里我提了个 issue 共建者给出了解答
@Data & @Builder 1.18.22 default constructor not found #3168
如果你仍然需要生成 private constructor 需要配置

lombok.noArgsConstructor.extraPrivate = true.

1.6.22 版本在升级时需要留意,如升级请确认升级后类构建后代码一致,使用 @Builder 时建议注解组合

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor

对具体复现流程,和原因感兴趣的同学可以继续往下看

验证流程

版本 1.16.22 生成

public class User {
    private String name;
    private int age;

    User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public static User.UserBuilder builder() {
        return new User.UserBuilder();
    }

    private User() {
    }

    public String getName() {
        return this.name;
    }

    public int getAge() {
        return this.age;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public boolean equals(Object o) {
        if (o == this) {
            return true;
        } else if (!(o instanceof User)) {
            return false;
        } else {
            User other = (User)o;
            if (!other.canEqual(this)) {
                return false;
            } else {
                Object this$name = this.getName();
                Object other$name = other.getName();
                if (this$name == null) {
                    if (other$name == null) {
                        return this.getAge() == other.getAge();
                    }
                } else if (this$name.equals(other$name)) {
                    return this.getAge() == other.getAge();
                }

                return false;
            }
        }
    }

    protected boolean canEqual(Object other) {
        return other instanceof User;
    }

    public int hashCode() {
        int PRIME = true;
        int result = 1;
        Object $name = this.getName();
        int result = result * 59 + ($name == null ? 43 : $name.hashCode());
        result = result * 59 + this.getAge();
        return result;
    }

    public String toString() {
        return "User(name=" + this.getName() + ", age=" + this.getAge() + ")";
    }

    public static class UserBuilder {
        private String name;
        private int age;

        UserBuilder() {
        }

        public User.UserBuilder name(String name) {
            this.name = name;
            return this;
        }

        public User.UserBuilder age(int age) {
            this.age = age;
            return this;
        }

        public User build() {
            return new User(this.name, this.age);
        }

        public String toString() {
            return "User.UserBuilder(name=" + this.name + ", age=" + this.age + ")";
        }
    }
}

版本 1.18.22 生成

public class User {
    private String name;
    private int age;

    User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public static User.UserBuilder builder() {
        return new User.UserBuilder();
    }

    public String getName() {
        return this.name;
    }

    public int getAge() {
        return this.age;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public boolean equals(Object o) {
        if (o == this) {
            return true;
        } else if (!(o instanceof User)) {
            return false;
        } else {
            User other = (User)o;
            if (!other.canEqual(this)) {
                return false;
            } else if (this.getAge() != other.getAge()) {
                return false;
            } else {
                Object this$name = this.getName();
                Object other$name = other.getName();
                if (this$name == null) {
                    if (other$name != null) {
                        return false;
                    }
                } else if (!this$name.equals(other$name)) {
                    return false;
                }

                return true;
            }
        }
    }

    protected boolean canEqual(Object other) {
        return other instanceof User;
    }

    public int hashCode() {
        int PRIME = true;
        int result = 1;
        int result = result * 59 + this.getAge();
        Object $name = this.getName();
        result = result * 59 + ($name == null ? 43 : $name.hashCode());
        return result;
    }

    public String toString() {
        return "User(name=" + this.getName() + ", age=" + this.getAge() + ")";
    }

    public static class UserBuilder {
        private String name;
        private int age;

        UserBuilder() {
        }

        public User.UserBuilder name(String name) {
            this.name = name;
            return this;
        }

        public User.UserBuilder age(int age) {
            this.age = age;
            return this;
        }

        public User build() {
            return new User(this.name, this.age);
        }

        public String toString() {
            return "User.UserBuilder(name=" + this.name + ", age=" + this.age + ")";
        }
    }
}

看一下对比,少了一个 private 的默认构造函数。

在这里插入图片描述

这会导致什么问题?比如我们常用的 fastjson

public class TestJsonFormat {

    public static void main(String[] args) {
        String userString="{\"age\":20,\"name\":\"dyinggq\"}";

        User user = JSONObject.parseObject(userString, User.class);
        System.out.println(user);

    }
}

在没有默认构造函数的情况下解析时会报错。而对于 1.16.22 版本生成私有默认构造函数

public class JavaBeanInfo {
				// 获取默认构造函数
        Constructor<?> defaultConstructor = null;
                if ((!kotlin) || constructors.length == 1) {
                    if (builderClass == null) {
                        defaultConstructor = getDefaultConstructor(clazz, constructors);
                    } else {
                        defaultConstructor = getDefaultConstructor(builderClass, builderClass.getDeclaredConstructors());
                    }
                }
				// 如果默认构造不可访问设置可访问
        if (defaultConstructor != null) {
            TypeUtils.setAccessible(defaultConstructor);
        }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dying 搁浅

两杯酒,一杯敬你余生多欢喜。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值