解决Failed toString() invocation on an object com.alibaba.fastjson.JSONException: write javaBean error

文章目录

  • 1. 复现问题
  • 2. 分析问题
  • 3. 解决问题

1. 复现问题

今天在启动spring boot项目,突然出现如下问题:

SLF4J: Failed toString() invocation on an object of type [com.superjson.superjsonmanager.config.jwt.JwtProperties$$EnhancerBySpringCGLIB$$3c58badf]
Reported exception:
com.alibaba.fastjson.JSONException: write javaBean error, fastjson version 1.2.70, class org.springframework.beans.factory.support.DefaultListableBeanFactory, fieldName : $$beanFactory, write javaBean error, fastjson version 1.2.70, class com.baomidou.mybatisplus.MybatisConfiguration, fieldName : configuration, write javaBean error, fastjson version 1.2.70, class com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceWrapper, fieldName : dataSource, write javaBean error, fastjson version 1.2.70, class com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl, fieldName : connection, write javaBean error, fastjson version 1.2.70, class com.mysql.cj.jdbc.ConnectionImpl, fieldName : connectionRaw, write javaBean error, fastjson version 1.2.70, class com.mysql.cj.jdbc.DatabaseMetaData, fieldName : metaData, write javaBean error, fastjson version 1.2.70, class com.mysql.cj.jdbc.result.ResultSetImpl, fieldName : catalogs
	at com.alibaba.fastjson.serializer.JavaBeanSerializer.write(JavaBeanSerializer.java:539)
	at com.alibaba.fastjson.serializer.JavaBeanSerializer.write(JavaBeanSerializer.java:149)
	at com.alibaba.fastjson.serializer.JSONSerializer.writeWithFieldName(JSONSerializer.java:333)
	at com.alibaba.fastjson.serializer.ASMSerializer_1_JwtProperties$$EnhancerBySpringCGLIB$$3c58badf.write(Unknown Source)
	at com.alibaba.fastjson.serializer.JSONSerializer.write(JSONSerializer.java:285)
	at com.alibaba.fastjson.JSON.toJSONString(JSON.java:758)
	at com.alibaba.fastjson.JSON.toJSONString(JSON.java:696)
	at com.alibaba.fastjson.JSON.toJSONString(JSON.java:661)
	at com.superjson.superjsonmanager.config.jwt.JwtProperties.toString(JwtProperties.java:73)
	at org.slf4j.helpers.MessageFormatter.safeObjectAppend(MessageFormatter.java:277)
	at org.slf4j.helpers.MessageFormatter.deeplyAppendParameter(MessageFormatter.java:249)
	at org.slf4j.helpers.MessageFormatter.arrayFormat(MessageFormatter.java:211)
	at org.slf4j.helpers.MessageFormatter.arrayFormat(MessageFormatter.java:161)
	at ch.qos.logback.classic.spi.LoggingEvent.getFormattedMessage(LoggingEvent.java:293)
	at ch.qos.logback.classic.spi.LoggingEvent.prepareForDeferredProcessing(LoggingEvent.java:206)
	at ch.qos.logback.core.OutputStreamAppender.subAppend(OutputStreamAppender.java:223)
	at ch.qos.logback.core.OutputStreamAppender.append(OutputStreamAppender.java:102)
	at ch.qos.logback.core.UnsynchronizedAppenderBase.doAppend(UnsynchronizedAppenderBase.java:84)
	at ch.qos.logback.core.spi.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttachableImpl.java:51)
	at ch.qos.logback.classic.Logger.appendLoopOnAppenders(Logger.java:270)
	at ch.qos.logback.classic.Logger.callAppenders(Logger.java:257)
	at ch.qos.logback.classic.Logger.buildLoggingEventAndAppend(Logger.java:421)
	at ch.qos.logback.classic.Logger.filterAndLog_1(Logger.java:398)
	at ch.qos.logback.classic.Logger.info(Logger.java:583)
	at com.superjson.superjsonmanager.SuperJsonManagerApplication.main(SuperJsonManagerApplication.java:51)
Caused by: com.alibaba.fastjson.JSONException: write javaBean error, fastjson version 1.2.70, class com.baomidou.mybatisplus.MybatisConfiguration, fieldName : configuration, write javaBean error, fastjson version 1.2.70, class com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceWrapper, fieldName : dataSource, write javaBean error, fastjson version 1.2.70, class com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl, fieldName : connection, write javaBean error, fastjson version 1.2.70, class com.mysql.cj.jdbc.ConnectionImpl, fieldName : connectionRaw, write javaBean error, fastjson version 1.2.70, class com.mysql.cj.jdbc.DatabaseMetaData, fieldName : metaData, write javaBean error, fastjson version 1.2.70, class com.mysql.cj.jdbc.result.ResultSetImpl, fieldName : catalogs
	at com.alibaba.fastjson.serializer.JavaBeanSerializer.write(JavaBeanSerializer.java:539)
	at com.alibaba.fastjson.serializer.JavaBeanSerializer.write(JavaBeanSerializer.java:149)
	at com.alibaba.fastjson.serializer.JSONSerializer.writeWithFieldName(JSONSerializer.java:333)
	at com.alibaba.fastjson.serializer.ASMSerializer_105_DefaultSqlSessionFactory.write(Unknown Source)
	at com.alibaba.fastjson.serializer.MapSerializer.write(MapSerializer.java:271)
	at com.alibaba.fastjson.serializer.MapSerializer.write(MapSerializer.java:44)
	at com.alibaba.fastjson.serializer.FieldSerializer.writeValue(FieldSerializer.java:320)
	at com.alibaba.fastjson.serializer.JavaBeanSerializer.write(JavaBeanSerializer.java:470)
	... 24 more

上述问题总结一句话是,使用alibaba.fastjson解析Javabean对象时,出现了错误,但为什么会出现这个问题呢?

2. 分析问题

我使用alibaba.fastjson解析JwtProperties对象报出上述错误的,该对象是用来存储jwt的参数,如下代码所示:

/**
 * @author zby
 * @datetime 2022/8/19 12:05
 * @desc jwt实体类,从yml配置文件中获取配置的属性
 */
@Getter
@Setter
@Configuration
@ConfigurationProperties(prefix = "jwt")
public class JwtProperties {

    @Value("${jwt.secret}")
    private String appSecret;

    @Value("${jwt.expiration}")
    private long expiration;

    @Value("${jwt.typ}")
    private String typ;

    @Value("${jwt.alg}")
    private String alg;

    @Value("${jwt.subject}")
    private String subject;

    @Value("${jwt.tokenStartWith}")
    private String tokenStartWith;

    @Value("${jwt.tokenHeader}")
    private String tokenHeader;

    public String getTokenStartWith() {
        return tokenStartWith + " ";
    }

    @Override
    @JSONField(serialize = false)
    public String toString() {
        return JSONObject.toJSONString(this);
    }
}

即重写toString()方法内部语句JSONObject.toJSONString(this);时出现了问题,于是断点看为何会出现这种问题,如下截图所示:

解决Failed toString() invocation on an object com.alibaba.fastjson.JSONException: write javaBean error_第1张图片

你会发现动态生成的JwtProperties的this对象并不是只有其属性值,而是还多了很多我并没有定义的属性值,为什么会出现这种情况呢?

应为spring boot采用动态代理的模式去实例化对象的,而这额外的属性值便是动态代理对象的属性值,因而,fastjson无法解析动态代理的属性值,故而报错。

3. 解决问题

既然知道错误的原因是spring boot 动态代理造成的,我们便不把对象交给spring boot动态代理,可以进行如下修改toString()方法:

@Override
@JSONField(serialize = false)
public String toString() {
  JSONObject jsonObject = new JSONObject();
  jsonObject.put("appSecret", this.appSecret);
  jsonObject.put("expiration", this.expiration);
  jsonObject.put("typ", this.typ);
  jsonObject.put("alg", this.alg);
  jsonObject.put("subject", this.subject);
  jsonObject.put("tokenStartWith", this.tokenStartWith);
  jsonObject.put("tokenHeader", this.tokenHeader);
  return JSONObject.toJSONString(jsonObject);
}

如此启动spring boot即可,如下图所示:

解决Failed toString() invocation on an object com.alibaba.fastjson.JSONException: write javaBean error_第2张图片

你可能感兴趣的:(java,java,spring,boot,后端,json,spring)