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] 反序列化 LinkedMultiValueMap时Array 变成了 JSONArray #2489

Closed
en-o opened this issue Apr 26, 2024 · 8 comments
Closed

[BUG] 反序列化 LinkedMultiValueMap时Array 变成了 JSONArray #2489

en-o opened this issue Apr 26, 2024 · 8 comments
Assignees
Labels
bug Something isn't working fixed
Milestone

Comments

@en-o
Copy link

en-o commented Apr 26, 2024

问题描述

我在接口请求数据 JSON.parseObject(respJson, LinkedMultiValueMap) 发现数据类型不一致,导致我后续的removeif出错

环境信息

请填写以下信息:

  • OS信息: windows
  • JDK信息:azul-17.0.10
  • 版本信息:Fastjson2.0.47

重现步骤

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

  1. 使用 xxx.xxx 方法
String respJson = HttpInvoker.httpGet(leader.getUrl() + "/test");
JSON.parseObject(respJson, Test.class)
  1. 输入 ... 数据
public class Test{
    LinkedMultiValueMap<String, InstanceMeta> test_1;
    Map<String, Long> test_2;
    Map<String, Long> test_3;
    long test_4;
}
  1. 出现 ... 错误
java.lang.ClassCastException create breakpoint : clas com.alibaba.fastjson2.JS0N0bject cannot be cast to class'cn.XX (com.alibaba.fastjson2.u0Nobject and cn.XX are in unnamed module of loader 'app')at cn.XX)~[classes/:na]

image

@en-o en-o added the bug Something isn't working label Apr 26, 2024
@wenshao wenshao self-assigned this Apr 27, 2024
@wenshao wenshao added this to the 2.0.50 milestone Apr 27, 2024
@wenshao
Copy link
Member

wenshao commented Apr 27, 2024

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

@805728578
Copy link

@wenshao 2.0.50版本计划什么时候发布

@wenshao
Copy link
Member

wenshao commented Apr 29, 2024

2.0.50计划在5月12日前发布

@en-o
Copy link
Author

en-o commented Apr 30, 2024

我这种嵌套太多的还是不行

错误

class cn.xx.core.model.InstanceMeta cannot be cast to class java.util.List (cn.xx.core.model.InstanceMeta is in unnamed module of loader 'app'; java.util.List is in module java.base of loader 'bootstrap')

数据

{"registry":{"cn.xx.UserService":[{"schema":"http","host":"127.0.0.1","port":8082,"context":"trpc","status":true,"parameters":{"env":"dev","tag":"red"}}]},"timestamps":{"cn.xx.UserService@http://127.0.0.1:8082/trpc":1714442794280},"versions":{"cn.xx.UserService":1},"version":1}
@Data
@AllArgsConstructor
public class Snapshot {

    /**
     * 注册上来的服务集
     */
//    @JSONField(deserializeUsing = LinkedMultiValueMapDeserializer.class)
    LinkedMultiValueMap<String, InstanceMeta> registry;


    /**
     * 实例时间戳  - 实例级别
     * (service + "@" + instance.toUrl(),时间戳)
     */
    Map<String, Long> timestamps;
    /**
     * 服务的版本 - 服务级别
     */
    Map<String, Long> versions;

    /**
     * VERSIONS#value
     */
    long version;

}
@Data
@NoArgsConstructor
@EqualsAndHashCode(of = {"schema", "host", "port", "context"})
public class InstanceMeta {

    /**
     * 协议 [http]
     */
    private String schema;

    /**
     * host
     */
    private String host;

    /**
     * port
     */
    private Integer port;

    /**
     * 上下文
     */
    private String context;

    /**
     * 服务状态
     */
    private Boolean status;
}

方法

// 都尝试过
JSON.to(clazz, respJson)
JSON.parseObject(respJson, typeReference);

@en-o
Copy link
Author

en-o commented Apr 30, 2024

我目前的解决方案给别人参考一下:可行的

public class LinkedMultiValueMapDeserializer implements ObjectReader<LinkedMultiValueMap<String, InstanceMeta>> {

    @Override
    public LinkedMultiValueMap<String, InstanceMeta> readObject(JSONReader jsonReader
            , Type fieldType
            , Object fieldName
            , long features) {
        LinkedMultiValueMap<String, InstanceMeta> linkedMultiValueMap = new LinkedMultiValueMap<>();

        Map<String, Object> jsonObject = jsonReader.readObject();
        for (Map.Entry<String, Object> entry : jsonObject.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();
            if(value instanceof JSONObject){
                InstanceMeta instanceMeta = ((JSONObject) value).to(InstanceMeta.class);
                linkedMultiValueMap.add(key, instanceMeta);
            }else if(value instanceof JSONArray){
                List<InstanceMeta> instanceMetas = JSONArray.parseArray(value.toString(), InstanceMeta.class);
                linkedMultiValueMap.addAll(key, instanceMetas);
            }
        }
        return linkedMultiValueMap;
    }
}
@Data
@AllArgsConstructor
public class Snapshot {

    @JSONField(deserializeUsing = LinkedMultiValueMapDeserializer.class)
    LinkedMultiValueMap<String, InstanceMeta> registry;
}

@wenshao wenshao removed the fixed label May 3, 2024
@wenshao
Copy link
Member

wenshao commented May 3, 2024

package com.alibaba.fastjson2.issues_2400;

import com.alibaba.fastjson2.JSON;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.junit.jupiter.api.Test;
import org.springframework.util.LinkedMultiValueMap;

import java.util.List;
import java.util.Map;

import static org.junit.jupiter.api.Assertions.*;

public class Issue2489 {
    @Test
    public void test() {
        String str = "{\"registry\":{\"cn.xx.UserService\":[{\"schema\":\"http\",\"host\":\"127.0.0.1\",\"port\":8082,\"context\":\"trpc\",\"status\":true,\"parameters\":{\"env\":\"dev\",\"tag\":\"red\"}}]},\"timestamps\":{\"cn.xx.UserService@http://127.0.0.1:8082/trpc\":1714442794280},\"versions\":{\"cn.xx.UserService\":1},\"version\":1}\n";
        Snapshot snapshot = JSON.parseObject(str, Snapshot.class);
        assertEquals(1, snapshot.registry.size());
        snapshot.registry.forEach((k, v) -> {
            assertEquals(String.class, k.getClass());
            for (InstanceMeta instanceMeta : v) {
                assertNotNull(instanceMeta);
            }
        });

        List<InstanceMeta> instanceMetas = snapshot.registry.get("cn.xx.UserService");
        assertEquals(1, instanceMetas.size());
        InstanceMeta instanceMeta = instanceMetas.get(0);
        assertEquals("http", instanceMeta.schema);
    }

    @Data
    @AllArgsConstructor
    public static class Snapshot {
        /**
         * 注册上来的服务集
         */
//    @JSONField(deserializeUsing = LinkedMultiValueMapDeserializer.class)
        LinkedMultiValueMap<String, InstanceMeta> registry;
        /**
         * 实例时间戳  - 实例级别
         * (service + "@" + instance.toUrl(),时间戳)
         */
        Map<String, Long> timestamps;
        /**
         * 服务的版本 - 服务级别
         */
        Map<String, Long> versions;

        /**
         * VERSIONS#value
         */
        long version;
    }

    @Data
    @NoArgsConstructor
    @EqualsAndHashCode(of = {"schema", "host", "port", "context"})
    public static class InstanceMeta {
        private String schema;
        private String host;
        private Integer port;
        private String context;
        private Boolean status;
    }
}

我测试没问题啊

@wenshao
Copy link
Member

wenshao commented May 3, 2024

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

@wenshao wenshao added the fixed label May 3, 2024
@wenshao
Copy link
Member

wenshao commented May 12, 2024

https://github.com/alibaba/fastjson2/releases/tag/2.0.50
2.0.50已发布,请用新版本

@wenshao wenshao closed this as completed May 12, 2024
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
Projects
None yet
Development

No branches or pull requests

3 participants