[alibaba/fastjson]fastjson 调用 toJavaObject 时无法转换属性中的 SortedSet 类型

2025-10-31 709 views
0

版本:1.2.41 定位到原因是在 TypeUtils.cast(Object obj, ParameterizedType type, ParserConfig mapping) 方法中对于集合类型,没有识别 SortedSet 类型。

public static <T> T cast(Object obj, ParameterizedType type, ParserConfig mapping){
        Type rawTye = type.getRawType();
        if(rawTye == Set.class || rawTye == HashSet.class //
                || rawTye == TreeSet.class //
                || rawTye == List.class //
                || rawTye == ArrayList.class){
            Type itemType = type.getActualTypeArguments()[0];
            if(obj instanceof Iterable){
                Collection collection;
                if(rawTye == Set.class || rawTye == HashSet.class){
                    collection = new HashSet();
                } else if(rawTye == TreeSet.class){
                    collection = new TreeSet();
                } else{
                    collection = new ArrayList();
                }
                for(Iterator it = ((Iterable) obj).iterator(); it.hasNext(); ){
                    Object item = it.next();
                    collection.add(cast(item, itemType, mapping));
                }
                return (T) collection;
            }
        }

       ....
}

回答

9

补充一个 case

public class FastjsonSortedSet {

    public static void main(String[] args) {
        VO v = new VO();
        SortedSet<String> ss = new TreeSet<>();
        ss.add("1");
        ss.add("2");
        v.setSs(ss);
        String str = JSON.toJSONString(v);
        JSONObject jsonObject = JSON.parseObject(str);
        jsonObject.toJavaObject(VO.class);
    }

    public static class VO {

        private SortedSet<String> ss;

        public SortedSet<String> getSs() {
            return ss;
        }

        public void setSs(SortedSet<String> ss) {
            this.ss = ss;
        }
    }

}

异常

Exception in thread "main" com.alibaba.fastjson.JSONException: can not cast to : java.util.SortedSet<java.lang.String>
    at com.alibaba.fastjson.util.TypeUtils.castToJavaBean(TypeUtils.java:927)
    at com.alibaba.fastjson.util.TypeUtils.cast(TypeUtils.java:621)
    at com.alibaba.fastjson.JSON.toJavaObject(JSON.java:924)
    at FastjsonSortedSet.main(FastjsonSortedSet.java:23)
Caused by: com.alibaba.fastjson.JSONException: can not cast to : java.util.SortedSet<java.lang.String>
    at com.alibaba.fastjson.util.TypeUtils.cast(TypeUtils.java:858)
    at com.alibaba.fastjson.util.TypeUtils.cast(TypeUtils.java:778)
    at com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer.createInstance(JavaBeanDeserializer.java:821)
    at com.alibaba.fastjson.util.TypeUtils.castToJavaBean(TypeUtils.java:925)
    ... 3 more
1

想到的方法是把 SortedSet 加入到 if 判断中,这样进行修复,如下面rawTye == SortedSet.class的代码。

public static <T> T cast(Object obj, ParameterizedType type, ParserConfig mapping){
        Type rawTye = type.getRawType();
        if(rawTye == Set.class || rawTye == HashSet.class //
                || rawTye == TreeSet.class //
                || rawTye == Collection.class //
                || rawTye == List.class //
                || rawTye == ArrayList.class
                || rawTye == SortedSet.class){
            Type itemType = type.getActualTypeArguments()[0];
            if(obj instanceof Iterable){
                Collection collection;
                if(rawTye == Set.class || rawTye == HashSet.class){
                    collection = new HashSet();
                } else if(rawTye == SortedSet.class || rawTye == TreeSet.class){
                    collection = new TreeSet();
                } else{
                    collection = new ArrayList();
                }
                for(Iterator it = ((Iterable) obj).iterator(); it.hasNext(); ){
                    Object item = it.next();
                    collection.add(cast(item, itemType, mapping));
                }
                return (T) collection;
            }
        }
  ...
1

在最新的源码中测试发现这个问题已经在 2017-12-14 的 0f30d9302cf759dcf5756bad5bd27e03ba66f0f8 这个 commit 中修复了。