[BUG] Dubbo 使用 Fastjson2.0.57 版本时提示 not support none-Serializable
问题描述
如下代码所示,Dubbo 使用 Fastjson 2.0.57 版本时提示报错:not support none-Serializable。 使用 Fastjson 2.0.56 及之前版本则一切正常。
环境信息
请填写以下信息:
- OS信息: Windows 10
- JDK信息:OpenJDK 17.0.14
- 版本信息:Fastjson 2.0.57
重现步骤
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
static class Message<T> implements Serializable {
T msg;
}
@Test
public void test() {
Message<String> obj = new Message<>("Hello");
byte[] bytes = JSONB.toBytes(obj, JSONWriter.Feature.WriteClassName,
JSONWriter.Feature.FieldBased,
JSONWriter.Feature.ErrorOnNoneSerializable,
JSONWriter.Feature.ReferenceDetection,
JSONWriter.Feature.WriteNulls,
JSONWriter.Feature.NotWriteDefaultValue,
JSONWriter.Feature.NotWriteHashMapArrayListClassName,
JSONWriter.Feature.WriteNameAsSymbol);
ContextAutoTypeBeforeHandler handler = new ContextAutoTypeBeforeHandler(true, obj.getClass());
Object result = JSONB.parseObject(bytes, obj.getClass(), handler,
JSONReader.Feature.UseDefaultConstructorAsPossible,
JSONReader.Feature.ErrorOnNoneSerializable,
JSONReader.Feature.IgnoreAutoTypeNotMatch,
JSONReader.Feature.UseNativeObject,
JSONReader.Feature.FieldBased);
}
期待的正确结果
一切正常
相关日志输出
com.alibaba.fastjson2.JSONException: not support none-Serializable
at com.alibaba.fastjson2.reader.FieldReaderObject.readFieldValueJSONB(FieldReaderObject.java:185)
at com.alibaba.fastjson2.reader.ObjectReaderAdapter.readFieldValue(ObjectReaderAdapter.java:506)
at com.alibaba.fastjson2.reader.ORG_1_1_Message.readJSONBObject(Unknown Source)
at com.alibaba.fastjson2.JSONB.parseObject(JSONB.java:569)
附加信息
如果将泛型 <T> 声明改为 <T extends Serializable>,就能够恢复正常。
dubbo调用出现RemotingException,provider端无异常,接口response带泛型,应该是一个问题
fastjson2 2.0.57
dubbo 3.2.9
cause: org.apache.dubbo.remoting.RemotingException: java.io.IOException: org.apache.dubbo.common.serialize.SerializationException: com.alibaba.fastjson2.JSONException: not support none-Serializable java.io.IOException: org.apache.dubbo.common.serialize.SerializationException: com.alibaba.fastjson2.JSONException: not support none-Serializable
Caused by: com.alibaba.fastjson2.JSONException: not support none-Serializable at com.alibaba.fastjson2.reader.FieldReaderObject.readFieldValueJSONB(FieldReaderObject.java:185) at com.alibaba.fastjson2.reader.ObjectReaderAdapter.readFieldValue(ObjectReaderAdapter.java:506) at com.alibaba.fastjson2.reader.ORG_24_4_AssignRegionResp.readJSONBObject(Unknown Source) at com.alibaba.fastjson2.reader.ObjectReaderImplObject.readJSONBObject(ObjectReaderImplObject.java:331) at com.alibaba.fastjson2.reader.FieldReaderObject.readFieldValueJSONB(FieldReaderObject.java:203) at com.alibaba.fastjson2.reader.ObjectReaderAdapter.readFieldValue(ObjectReaderAdapter.java:506) at com.alibaba.fastjson2.reader.ORG_10_4_UtopiaResponseModel.readJSONBObject(Unknown Source) at com.alibaba.fastjson2.JSONB.parseObject(JSONB.java:569) at org.apache.dubbo.common.serialize.fastjson2.FastJson2ObjectInput.readObject(FastJson2ObjectInput.java:161) at org.apache.dubbo.common.serialize.DefaultSerializationExceptionWrapper$ProxyObjectInput.readObject(DefaultSerializationExceptionWrapper.java:170)
@wenshao 看了下fix的代码,非包装类在对应的场景中还是会出现“not support none-Serializable”
@Razor0719 因为配置了ErrorOnNoneSerializable,这里更严格一下会更安全,因为这里的T确实是限定在Serializable,按理来说,应该是全部报错才更合适的。
https://oss.sonatype.org/content/repositories/snapshots/com/alibaba/fastjson2/fastjson2/2.0.58-SNAPSHOT/ 问题已修复,请帮忙用2.0.58-SNAPSHOT版本验证
传参带泛型 还是不行 [2.0.58-SNAPSHOT 这个版本还是不能用
https://github.com/alibaba/fastjson2/releases/tag/2.0.58 问题已修复,请用新版本
https://github.com/alibaba/fastjson2/releases/tag/2.0.58 问题已修复,请用新版本
已升级2.0.58,经过测试,依旧报错,只能回退2.0.56
@wenshao 同使用2.0.58仍然遇到这个报错,请问2.0.59会修复该问题吗?
我目前已降级到2.0.56,生产环境经不起这么玩
---- 回复的原邮件 ---- | 发件人 | @.> | | 发送日期 | 2025年08月20日 10:26 | | 收件人 | alibaba/fastjson2 @.> | | 抄送人 | JeckXu @.>, Comment @.> | | 主题 | Re: [alibaba/fastjson2] [BUG] Dubbo 使用 Fastjson2.0.57 版本时提示 not support none-Serializable (Issue #3499) | njufancy left a comment (alibaba/fastjson2#3499)
@wenshao 同使用2.0.58仍然遇到这个报错,请问2.0.59会修复该问题吗?
— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you commented.Message ID: @.***>
看起来是一个严重问题,能帮忙构造重现问题的testcase,如果能够重现,我会快速修复并且发布新版本
我这边的case是这样的 服务端 CommonResult定义: @Data @NoArgsConstructor public class CommonResult<T> implements Serializable { private int code; private String message; private T data; }
提供dubbo接口:CommonResult<TestDTO> testMethod(TestReq req);
客户端 dubbo 3.2.11 fastjson 2.0.58,调用该接口报错 not support none-Serializable
public class Issue3499WithoutFix {
/**
* This test demonstrates the issue that was fixed in commit c1b0b6382.
* Before the fix, using ErrorOnNoneSerializable with generic types would throw
* "not support none-Serializable" even when the generic type implements Serializable.
*/
@Test
public void testGenericMessageWithSerializable() {
// This should work fine - Message implements Serializable and String is serializable
Message<String> obj = new Message<>("Hello");
byte[] bytes = JSONB.toBytes(obj, JSONWriter.Feature.WriteClassName,
JSONWriter.Feature.FieldBased,
JSONWriter.Feature.ErrorOnNoneSerializable); // This feature was causing the issue
ContextAutoTypeBeforeHandler handler = new ContextAutoTypeBeforeHandler(true, obj.getClass());
Object result = JSONB.parseObject(bytes, obj.getClass(), handler,
JSONReader.Feature.ErrorOnNoneSerializable); // This feature was causing the issue
assertEquals(obj.getMsg(), ((Message<String>) result).getMsg());
}
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
static class Message<T>
implements Serializable {
T msg;
}
}
@njufancy 没重现问题
我这里的 原因是实体类 boolean为true时,会反序列化失败, 版本 2.0.59
public class NoneSerializableTest {
@Setter
@Getter
public static class ParentTestOrder implements Serializable {
private static final long serialVersionUID = 721230004160956721L;
private boolean flag ;
}
@Setter
@Getter
public static class TestOrder extends ParentTestOrder {
private String name;
}
@Test
public void doTest() {
TestOrder order = new TestOrder();
order.setName("test");
order.setFlag(true);
byte[] bytes1 = JSONB.toBytes(
order,
JSONWriter.Feature.WriteClassName,
JSONWriter.Feature.FieldBased,
JSONWriter.Feature.ErrorOnNoneSerializable,
JSONWriter.Feature.ReferenceDetection,
JSONWriter.Feature.WriteNulls,
JSONWriter.Feature.NotWriteDefaultValue,
JSONWriter.Feature.NotWriteHashMapArrayListClassName,
JSONWriter.Feature.WriteNameAsSymbol);
JSONB.parseObject(
bytes1,
TestOrder.class,
JSONReader.Feature.UseDefaultConstructorAsPossible,
JSONReader.Feature.ErrorOnNoneSerializable,
JSONReader.Feature.IgnoreAutoTypeNotMatch,
JSONReader.Feature.UseNativeObject,
JSONReader.Feature.FieldBased);
}
}
运行提示: com.alibaba.fastjson2.JSONException: not support none-Serializable
at com.alibaba.fastjson2.reader.FieldReaderObject.readFieldValueJSONB(FieldReaderObject.java:187)
at com.alibaba.fastjson2.reader.ObjectReaderAdapter.readFieldValue(ObjectReaderAdapter.java:507)
at com.alibaba.fastjson2.reader.ORG_1_2_TestOrder.readJSONBObject(Unknown Source)
at com.alibaba.fastjson2.JSONB.parseObject(JSONB.java:1174)
at com.sjit.procure.account.test.user.NoneSerializableTest.doTest(NoneSerializableTest.java:62)
只要 order.setFlag(false); 设置为false是,就不会报错
希望兄弟破案🙏😂
---- 回复的原邮件 ---- | 发件人 | @.> | | 发送日期 | 2025年10月16日 10:58 | | 收件人 | alibaba/fastjson2 @.> | | 抄送人 | JeckXu @.>, Comment @.> | | 主题 | Re: [alibaba/fastjson2] [BUG] Dubbo 使用 Fastjson2.0.57 版本时提示 not support none-Serializable (Issue #3499) | cnwolffy left a comment (alibaba/fastjson2#3499)
我这里的 原因是实体类 boolean为true时,会反序列化失败
public class NoneSerializableTest {
@Setter @Getter public static class ParentTestOrder implements Serializable { private static final long serialVersionUID = 721230004160956721L; private boolean flag ; }
@Setter @Getter public static class TestOrder extends ParentTestOrder { private String name; }
@Test public void doTest() { TestOrder order = new TestOrder(); order.setName("test"); order.setFlag(true);
byte[] bytes1 = JSONB.toBytes(
order,
JSONWriter.Feature.WriteClassName,
JSONWriter.Feature.FieldBased,
JSONWriter.Feature.ErrorOnNoneSerializable,
JSONWriter.Feature.ReferenceDetection,
JSONWriter.Feature.WriteNulls,
JSONWriter.Feature.NotWriteDefaultValue,
JSONWriter.Feature.NotWriteHashMapArrayListClassName,
JSONWriter.Feature.WriteNameAsSymbol);
JSONB.parseObject(
bytes1,
TestOrder.class,
JSONReader.Feature.UseDefaultConstructorAsPossible,
JSONReader.Feature.ErrorOnNoneSerializable,
JSONReader.Feature.IgnoreAutoTypeNotMatch,
JSONReader.Feature.UseNativeObject,
JSONReader.Feature.FieldBased);
}
}
运行提示: com.alibaba.fastjson2.JSONException: not support none-Serializable
at com.alibaba.fastjson2.reader.FieldReaderObject.readFieldValueJSONB(FieldReaderObject.java:187) at com.alibaba.fastjson2.reader.ObjectReaderAdapter.readFieldValue(ObjectReaderAdapter.java:507) at com.alibaba.fastjson2.reader.ORG_1_2_TestOrder.readJSONBObject(Unknown Source) at com.alibaba.fastjson2.JSONB.parseObject(JSONB.java:1174) at com.sjit.procure.account.test.user.NoneSerializableTest.doTest(NoneSerializableTest.java:62)
只要 order.setFlag(false); 设置为false是,就不会报错
— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you commented.Message ID: @.***>
@cnwolffy 感谢反馈,问题已重现,我会尽快修复并且发布新版本
问题已修复,请帮忙用这个仓库的 https://central.sonatype.com/repository/maven-snapshots 2.0.60-SNAPSHOT版本验证下
https://github.com/alibaba/fastjson2/releases/tag/2.0.60 问题已修复,请用新版本
经过测试,目前还存在问题,案例为:R<Map<Long, String>> xxx(Request request); 完整的R结构: @Schema( description = "返回信息" ) public class R<T> implements Serializable { private static final long serialVersionUID = 1L; @Schema( description = "状态码", requiredMode = RequiredMode.REQUIRED ) private int code; @Schema( description = "是否成功", requiredMode = RequiredMode.REQUIRED ) private boolean success; @Schema( description = "承载数据" ) private T data; @Schema( description = "返回消息", requiredMode = RequiredMode.REQUIRED ) private String msg; @Schema( description = "日志追踪ID" ) private String traceId; @Schema( description = "全局请求ID" ) private String requestId; @Schema( description = "当前时间戳" ) private String timestamp; @Schema( description = "当前日期时间" ) private String time;
private R(IResultCode resultCode) {
this(resultCode, (Object)null, resultCode.getMessage());
}
private R(IResultCode resultCode, String msg) {
this(resultCode, (Object)null, msg);
}
private R(IResultCode resultCode, T data) {
this(resultCode, data, resultCode.getMessage());
}
private R(IResultCode resultCode, T data, String msg) {
this(resultCode.getCode(), data, msg);
}
private R(int code, T data, String msg) {
this.timestamp = Long.toString(System.currentTimeMillis());
this.time = DateUtil.formatDateTime(new Date());
this.code = code;
this.data = data;
this.msg = msg;
this.traceId = MDC.get("traceId");
this.requestId = MDC.get("requestId");
this.success = ResultCode.SUCCESS.code == code;
}
public static boolean isSuccess(@Nullable R<?> r) {
return (Boolean)Optional.ofNullable(r).map((x) -> ObjectUtil.nullSafeEquals(ResultCode.SUCCESS.code, x.code)).orElse(Boolean.FALSE);
}
public static boolean isNotSuccess(@Nullable R<?> r) {
return !isSuccess(r);
}
public static <T> R<T> data(T data) {
return data(data, I18nMessageUtils.get("ROOT.OPERATION_SUCCESS"));
}
public static <T> R<T> data(T data, String msg) {
return data(200, data, msg);
}
public static <T> R<T> data(int code, T data, String msg) {
return new R<T>(code, data, data == null ? I18nMessageUtils.get("ROOT.NO_DATA") : msg);
}
public static <T> R<T> success(String msg) {
return new R<T>(ResultCode.SUCCESS, msg);
}
public static <T> R<T> success() {
return new R<T>(ResultCode.SUCCESS, I18nMessageUtils.get("ROOT.OPERATION_SUCCESS"));
}
public static <T> R<T> success(IResultCode resultCode) {
return new R<T>(resultCode);
}
public static <T> R<T> success(IResultCode resultCode, String msg) {
return new R<T>(resultCode, msg);
}
public static <T> R<T> fail() {
return new R<T>(ResultCode.FAILURE, I18nMessageUtils.get("ROOT.OPERATION_FAILED"));
}
public static <T> R<T> fail(String msg) {
return new R<T>(ResultCode.FAILURE, msg);
}
public static <T> R<T> fail(int code, String msg) {
return new R<T>(code, (Object)null, msg);
}
public static <T> R<T> fail(IResultCode resultCode) {
return new R<T>(resultCode);
}
public static <T> R<T> fail(IResultCode resultCode, String msg) {
return new R<T>(resultCode, msg);
}
public static <T> R<T> status(boolean flag) {
return flag ? success(I18nMessageUtils.get("ROOT.OPERATION_SUCCESS")) : fail(I18nMessageUtils.get("ROOT.OPERATION_FAILED"));
}
public int getCode() {
return this.code;
}
public boolean isSuccess() {
return this.success;
}
public T getData() {
return this.data;
}
public String getMsg() {
return this.msg;
}
public String getTraceId() {
return this.traceId;
}
public String getRequestId() {
return this.requestId;
}
public void setCode(final int code) {
this.code = code;
}
public void setSuccess(final boolean success) {
this.success = success;
}
public void setData(final T data) {
this.data = data;
}
public void setMsg(final String msg) {
this.msg = msg;
}
public void setTraceId(final String traceId) {
this.traceId = traceId;
}
public void setRequestId(final String requestId) {
this.requestId = requestId;
}
public String getTimestamp() {
return this.timestamp;
}
public void setTimestamp(String timestamp) {
this.timestamp = timestamp;
}
public String getTime() {
return this.time;
}
public void setTime(String time) {
this.time = time;
}
public String toString() {
return MoreObjects.toStringHelper(this).add("code", this.code).add("success", this.success).add("data", this.data).add("msg", this.msg).add("traceId", this.traceId).add("requestId", this.requestId).add("timestamp", this.timestamp).add("time", this.time).toString();
}
public R() {
this.timestamp = Long.toString(System.currentTimeMillis());
this.time = DateUtil.formatDateTime(new Date());
}
}