Skip to content

Conversation

@ban-xiu
Copy link

@ban-xiu ban-xiu commented Jan 3, 2026

What this PR does / why we need it?

Fix: 修复自定义 List 子类反序列化时元素类型解析为 JSONObject 的问题 issus_3926

恳请帮忙审查并合并此 PR,希望能为项目贡献一份力量

根本原因

在 ObjectReaderCreator.createFieldReader() 方法中,当字段类型是自定义 List 子类(如 MyList.class )时:

  1. fieldTypeResolved 不是 ParameterizedType ,无法提取泛型类型参数
  2. fieldType 是普通 Class (不是 ParameterizedType ),也无法提取泛型类型参数
  3. 最终 itemType 被设置为 Object.class ,导致反序列化时创建 JSONObject

解决方案

在 ObjectReaderCreator.java 的 List 类型解析逻辑中,新增第三步类型解析策略:

  1. 第一步 :从 fieldTypeResolved 提取类型参数(原有逻辑)
  2. 第二步 :从 fieldType 提取类型参数(原有逻辑)
  3. 第三步 :遍历 fieldType 的泛型超类层次结构,查找包含泛型类型参数的 Collection 超类
    另外处理了fieldTypeResolved fieldClassResolved为空的情况

Summary of your change

core/src/main/java/com/alibaba/fastjson2/reader/ObjectReaderCreator.java,在 createFieldReader() 方法中,针对 List 类型的字段解析逻辑进行了增强

core/src/test/java/com/alibaba/fastjson2_demo/CustomListTest.java,添加了测试用例验证修复效果

Please indicate you've done the following:

  • Made sure tests are passing and test coverage is added if needed.
  • Made sure commit message follow the rule of Conventional Commits specification.
  • Considered the docs impact and opened a new docs issue or PR with docs changes if needed.

@CLAassistant
Copy link

CLAassistant commented Jan 3, 2026

CLA assistant check
All committers have signed the CLA.

@jujn
Copy link
Collaborator

jujn commented Jan 3, 2026

谢谢你的支持,我最近也在研究这个,有几个建议供你参考:
①对于直接实现接口的场景(如下),目前的修复可能还存在一些缺陷

public class MyList implements List<String> { ... }

②单测可以补充一下 FieldBased 的场景:

MyDTO myDTO = JSON.parseObject("{\"myList\":[{\"name\":\"张三\"}]}", MyDTO.class, JSONReader.Feature.FieldBased);
MyObject myObject = myDTO.getMyList().get(0);

③单测类的命名、放置位置、编写风格 可以参考下其它已合并的 PR

@ban-xiu
Copy link
Author

ban-xiu commented Jan 3, 2026

@jujn 好的我研究一下

@ban-xiu
Copy link
Author

ban-xiu commented Jan 4, 2026

@jujn hi,已经完成了接口解析的补充和自测,请问可以帮忙review一下吗

@jujn
Copy link
Collaborator

jujn commented Jan 4, 2026

MyDTO myDTO = JSON.parseObject("{"myList":[{"name":"张三"}]}", MyDTO.class, JSONReader.Feature.FieldBased);
FieldBased 的场景也需要修复(在 ObjectReaderCreator 某一个 createFieldReader 中,你可以自己找一下hh),增加与 createFieldReaderMethod 相类似的逻辑即可。因为这两种情况,一个是基于setter解析,一个基于field。

@ban-xiu
Copy link
Author

ban-xiu commented Jan 5, 2026

@jujn 搞定了辛苦帮忙看看

@jujn
Copy link
Collaborator

jujn commented Jan 5, 2026

可以改成这样吗?

if (fieldTypeResolved instanceof ParameterizedType) {
  // 这里的逻辑不要动
  …… 
} else {
   调用 BeanUtils.resolveCollectionItemType
   ……
}

@ban-xiu
Copy link
Author

ban-xiu commented Jan 5, 2026

已修改

@jujn
Copy link
Collaborator

jujn commented Jan 5, 2026

resolveCollectionItemType 里可以复用 BeanUtils.getGenericSupertype 方法吗?(比如类似下面这样的逻辑)

    public static Type resolveCollectionItemType(Type fieldTypeResolved, Class<?> fieldClass) {
        Type contextType = fieldTypeResolved != null ? fieldTypeResolved : fieldClass;

        Type listType = getGenericSupertype(contextType, fieldClass, List.class);

        if (listType == null || listType == List.class) {
            listType = getGenericSupertype(contextType, fieldClass, Collection.class);
        }

        listType = BeanUtils.resolve(contextType, fieldClass, listType);

        if (listType instanceof ParameterizedType) {
            ParameterizedType parameterizedType = (ParameterizedType) listType;
            Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();

            if (actualTypeArguments.length == 1) {
                return actualTypeArguments[0];
            }
        }
        return null;
    }

@ban-xiu
Copy link
Author

ban-xiu commented Jan 5, 2026

感谢指正,确实有很多可以复用的方法

@ban-xiu
Copy link
Author

ban-xiu commented Jan 5, 2026

已经做出修改

@ban-xiu
Copy link
Author

ban-xiu commented Jan 5, 2026

不知道为什么,图片中的评论我展示不出来,现在调整过了

@jujn
Copy link
Collaborator

jujn commented Jan 6, 2026

等温老师有时间来审核吧,这里我感觉很容易留下逻辑漏洞

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants