Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] Fastjson1 带 $ref 的数据在 fastjson2 无法正确反序列化 #2296

Closed
He-Pin opened this issue Mar 6, 2024 · 9 comments
Closed
Labels
bug Something isn't working fixed good first issue Good for newcomers
Milestone

Comments

@He-Pin
Copy link

He-Pin commented Mar 6, 2024

问题描述

简要描述您碰到的问题。
数据是用 fastjson 1 带引用写入的,结果在 消费侧用 fastjson2 反序列化时失败。

环境信息

请填写以下信息:

  • OS信息: [e.g.:CentOS 8.4.2105 4Core 3.10GHz 16 GB]
  • JDK信息: [e.g.:Openjdk 1.8.0_3]
  • 版本信息:[e.g.:Fastjson2 2.0.47]

重现步骤

如何操作可以重现该问题:

    @Test
    void streamConfigfromJSONStringCase1(){
        final String jsonConfig = "{\n" +
            "  \"streamConfigs\": {\n" +
            "    \"CHAT\": {\n" +
            "      \"batchingConfig\": {\n" +
            "        \"enableBatching\": false,\n" +
            "        \"enableEmptyFraming\": false,\n" +
            "        \"maxBatchInterval\": 1000,\n" +
            "        \"maxBatchSize\": 1024,\n" +
            "        \"maxMsgCount\": 10,\n" +
            "        \"maxMsgCountPerSubscriber\": 15\n" +
            "      },\n" +
            "      \"deliveryConfig\": {\n" +
            "        \"accsDeliveryStrategy\": \"RELIABILITY\",\n" +
            "        \"distinctInMillis\": 5000,\n" +
            "        \"enableDistinction\": true,\n" +
            "        \"enableMessageOrdering\": true,\n" +
            "        \"redundance\": 1,\n" +
            "        \"sendReliably\": true\n" +
            "      },\n" +
            "      \"flowControlConfig\": {\n" +
            "        \"enableThrottling\": true,\n" +
            "        \"overFlowStrategy\": \"Fail\",\n" +
            "        \"perUserLimitPerSecond\": 10,\n" +
            "        \"receiveQueueSize\": 1024,\n" +
            "        \"throttle\": 1\n" +
            "      },\n" +
            "      \"messageTarget\": {\n" +
            "        \"messageTargetType\": \"TOPIC\",\n" +
            "        \"topicId\": {\n" +
            "          \"businessId\": {\n" +
            "            \"namespace\": 37\n" +
            "          },\n" +
            "          \"namespaceAlias\": \"37\",\n" +
            "          \"uniqueTopicId\": \"snakeOnline-test-10087\"\n" +
            "        }\n" +
            "      },\n" +
            "      \"notifyOrCallbackConfig\": {\n" +
            "        \"idleNotifyIntervalInMillis\": 3000,\n" +
            "        \"idleNotifyThreshold\": -1,\n" +
            "        \"inboundMessageNotifyFilters\": null,\n" +
            "        \"outboundFrameCallbackFilters\": null,\n" +
            "        \"outboundMessageCallbackFilters\": null,\n" +
            "        \"unreachableNotifyIntervalInMillis\": 3000,\n" +
            "        \"unreachableNotifyThreshold\": -1\n" +
            "      },\n" +
            "      \"sequencerType\": \"PERSISTENT\"\n" +
            "    },\n" +
            "    \"MAIN\": {\n" +
            "      \"batchingConfig\": {\n" +
            "        \"enableBatching\": true,\n" +
            "        \"enableEmptyFraming\": true,\n" +
            "        \"maxBatchInterval\": 1000,\n" +
            "        \"maxBatchSize\": 2048,\n" +
            "        \"maxMsgCount\": 2,\n" +
            "        \"maxMsgCountPerSubscriber\": 15\n" +
            "      },\n" +
            "      \"deliveryConfig\": {\n" +
            "        \"accsDeliveryStrategy\": \"LOW_DELAY\",\n" +
            "        \"distinctInMillis\": 5000,\n" +
            "        \"enableDistinction\": true,\n" +
            "        \"enableMessageOrdering\": true,\n" +
            "        \"redundance\": 1,\n" +
            "        \"sendReliably\": true\n" +
            "      },\n" +
            "      \"flowControlConfig\": {\n" +
            "        \"enableThrottling\": false,\n" +
            "        \"overFlowStrategy\": \"Fail\",\n" +
            "        \"perUserLimitPerSecond\": 10,\n" +
            "        \"receiveQueueSize\": 1024,\n" +
            "        \"throttle\": 1\n" +
            "      },\n" +
            "      \"messageTarget\": {\n" +
            "        \"messageTargetType\": \"TOPIC\",\n" +
            "        \"topicId\": {\n" +
            "          \"$ref\": \"$.streamConfigs.CHAT.messageTarget.topicId\"\n" +
            "        }\n" +
            "      },\n" +
            "      \"notifyOrCallbackConfig\": {\n" +
            "        \"idleNotifyIntervalInMillis\": 3000,\n" +
            "        \"idleNotifyThreshold\": 30,\n" +
            "        \"inboundMessageNotifyFilters\": null,\n" +
            "        \"outboundFrameCallbackFilters\": null,\n" +
            "        \"outboundMessageCallbackFilters\": null,\n" +
            "        \"unreachableNotifyIntervalInMillis\": 3000,\n" +
            "        \"unreachableNotifyThreshold\": 5\n" +
            "      },\n" +
            "      \"sequencerType\": \"IN_MEMORY\"\n" +
            "    }\n" +
            "  },\n" +
            "  \"subscriberIdType\": \"USER\",\n" +
            "  \"ttl\": 94867200\n" +
            "}";
        final PmTopicConfig pmTopicConfig = CommonUtil.parseObject(
            jsonConfig, PmTopicConfig.class);
        Assertions.assertNotNull(pmTopicConfig.getStreamConfigs().get("MAIN").getMessageTarget().getTopicId().getUniqueTopicId());
    }

期待的正确结果

对您期望发生的结果进行清晰简洁的描述。

        "          \"$ref\": \"$.streamConfigs.CHAT.messageTarget.topicId\"\n" +

这个应该正确替换才对。

正确解析

相关日志输出

请复制并粘贴任何相关的日志输出。

附加信息

如果你还有其他需要提供的信息,可以在这里填写(可以提供截图、视频等)。

@He-Pin He-Pin added the bug Something isn't working label Mar 6, 2024
@rowstop
Copy link
Contributor

rowstop commented Mar 7, 2024

这个方法的代码能看下吗?
CommonUtil.parseObject(jsonConfig, PmTopicConfig.class);
是否是类似于这个逻辑

        JSONObject jsonObject = JSON.parseObject(jsonConfig);
        PmTopicConfig pmTopicConfig = jsonObject.to(PmTopicConfig.class);

如果是下面这个逻辑应该没问题的

        JSON.parseObject(jsonConfig, PmTopicConfig.class)

wenshao pushed a commit that referenced this issue Mar 8, 2024
…2296 (#2299)

* nextIfComma supports ignoring all white space chars, for issue #2164
* fix JSONReader#readObject unprocessed reference detection,for issue #2296
@wenshao
Copy link
Member

wenshao commented Mar 9, 2024

https://oss.sonatype.org/content/repositories/snapshots/com/alibaba/fastjson2/fastjson2/2.0.48-SNAPSHOT/
问题已修复,请帮忙用2.0.48-SNAPSHOT版本帮忙验证,2.0.48版本预计在3月底前发布。

@wenshao wenshao added this to the 2.0.48 milestone Mar 9, 2024
@wenshao wenshao added good first issue Good for newcomers fixed labels Mar 9, 2024
@He-Pin
Copy link
Author

He-Pin commented Mar 9, 2024

@wenshao @rowstop 感谢,我看了下单元测试很全面。本来说周末来研究下的:)

@wenshao 辛苦在阿里内网仓库打个snapshot,谢谢。

@wenshao
Copy link
Member

wenshao commented Mar 25, 2024

@wenshao wenshao closed this as completed Mar 25, 2024
@He-Pin
Copy link
Author

He-Pin commented Mar 25, 2024

反馈:2.0.48版本,两种使用方式得到不一样的结果:
@wenshao @rowstop
这个写法还是失败:

JSON.parseObject(jsonConfig, PmTopicConfig.class)

返回:
image

下面的这个写法OK的,修复了。

JSONObject jsonObject = JSON.parseObject(jsonConfig);
PmTopicConfig pmTopicConfig = jsonObject.to(PmTopicConfig.class);

image

@He-Pin
Copy link
Author

He-Pin commented Mar 25, 2024

反馈问题2:如果使用:

        final JSONObject jsonObject = JSON.parseObject(jsonConfig);
        final PmTopicConfig pmTopicConfig = jsonObject.toJavaObject(PmTopicConfig.class);


PmTopicConfig 类中的

    private HashMap<String, PmStreamConfig> streamConfigs = new HashMap<>();

在反序列化后,未被正确替换为 PmStreamConfig, 对象,hasmap 中放的是 JSONObject.

@rowstop
Copy link
Contributor

rowstop commented Mar 25, 2024

你这边先 检查下你的代码,我这里没有复现,你使用的是fastjson1的兼容版本?
toJavaObject 走的是 to 的逻辑

   public <T> T toJavaObject(Class<T> clazz, JSONReader.Feature... features) {
        return to(clazz, features);
    }

JSON.parseObject(jsonConfig,PmTopicConfig.class)
image

@wenshao wenshao modified the milestones: 2.0.48, 2.0.49 Mar 25, 2024
@He-Pin
Copy link
Author

He-Pin commented Mar 25, 2024

我拉一下主干代码,本地测试下,晚点回报。

@rowstop 我刚刚diff 了下本地的代码,应该是下面的这个部分导致的。

image

@He-Pin
Copy link
Author

He-Pin commented Mar 25, 2024

image
这个地方我看了下,delegate 到这边后无法判断是否对象是一个 reference,是否可以添加一个 reader.readOrResolveObject 方法?我看代码好像是添加 resolveTask,最后在一起resolve的。
目前我通过 :

        final JSONObject jsonObject = JSON.parseObject(json);
        return JSON.parseObject(jsonObject.toJSONString(), clazz);

可以得到我想要的结果。

同时,

        final JSONObject jsonObject = JSON.parseObject(jsonConfig);

        final PmTopicConfig pmTopicConfig = jsonObject.toJavaObject(PmTopicConfig.class);
        Assertions.assertNotNull(pmTopicConfig.getStreamConfigs().get("MAIN").getMessageTarget().getTopicId().getUniqueTopicId());

image

image

会触发:

java.lang.ClassCastException: class com.alibaba.fastjson2.JSONObject cannot be cast to class com.taobao.powermsg3.sdk.config.PmStreamConfig (com.alibaba.fastjson2.JSONObject and com.taobao.powermsg3.sdk.config.PmStreamConfig are in unnamed module of loader io.pandora.classloader.FilterLaunchedURLClassLoader @2b5f4d54)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working fixed good first issue Good for newcomers
Projects
None yet
Development

No branches or pull requests

3 participants