fastjson2 icon indicating copy to clipboard operation
fastjson2 copied to clipboard

[BUG] Dubbo 使用 Fastjson2.0.57 版本时提示 not support none-Serializable

Open CodePlayer opened this issue 8 months ago • 17 comments

问题描述

如下代码所示,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>,就能够恢复正常。

CodePlayer avatar Apr 16 '25 13:04 CodePlayer

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)

Razor0719 avatar Apr 22 '25 05:04 Razor0719

Image

Image

@wenshao 看了下fix的代码,非包装类在对应的场景中还是会出现“not support none-Serializable”

Razor0719 avatar Apr 24 '25 06:04 Razor0719

@Razor0719 因为配置了ErrorOnNoneSerializable,这里更严格一下会更安全,因为这里的T确实是限定在Serializable,按理来说,应该是全部报错才更合适的。

https://oss.sonatype.org/content/repositories/snapshots/com/alibaba/fastjson2/fastjson2/2.0.58-SNAPSHOT/ 问题已修复,请帮忙用2.0.58-SNAPSHOT版本验证

wenshao avatar Apr 26 '25 10:04 wenshao

传参带泛型 还是不行 [2.0.58-SNAPSHOT 这个版本还是不能用

zhaoyuasd avatar Jul 04 '25 01:07 zhaoyuasd

https://github.com/alibaba/fastjson2/releases/tag/2.0.58 问题已修复,请用新版本

wenshao avatar Jul 30 '25 05:07 wenshao

https://github.com/alibaba/fastjson2/releases/tag/2.0.58 问题已修复,请用新版本

已升级2.0.58,经过测试,依旧报错,只能回退2.0.56

ChinaJeckXu avatar Jul 31 '25 03:07 ChinaJeckXu

@wenshao 同使用2.0.58仍然遇到这个报错,请问2.0.59会修复该问题吗?

njufancy avatar Aug 20 '25 02:08 njufancy

我目前已降级到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: @.***>

ChinaJeckXu avatar Aug 20 '25 05:08 ChinaJeckXu

看起来是一个严重问题,能帮忙构造重现问题的testcase,如果能够重现,我会快速修复并且发布新版本

wenshao avatar Aug 20 '25 07:08 wenshao

我这边的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

njufancy avatar Aug 21 '25 02:08 njufancy

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 没重现问题

wenshao avatar Aug 21 '25 07:08 wenshao

我这里的 原因是实体类 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是,就不会报错

cnwolffy avatar Oct 16 '25 02:10 cnwolffy

希望兄弟破案🙏😂

---- 回复的原邮件 ---- | 发件人 | @.> | | 发送日期 | 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: @.***>

ChinaJeckXu avatar Oct 16 '25 03:10 ChinaJeckXu

@cnwolffy 感谢反馈,问题已重现,我会尽快修复并且发布新版本

wenshao avatar Oct 16 '25 13:10 wenshao

问题已修复,请帮忙用这个仓库的 https://central.sonatype.com/repository/maven-snapshots 2.0.60-SNAPSHOT版本验证下

wenshao avatar Oct 16 '25 16:10 wenshao

https://github.com/alibaba/fastjson2/releases/tag/2.0.60 问题已修复,请用新版本

wenshao avatar Oct 25 '25 11:10 wenshao

经过测试,目前还存在问题,案例为: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());
}

}

ChinaJeckXu avatar Nov 03 '25 15:11 ChinaJeckXu