fastjson icon indicating copy to clipboard operation
fastjson copied to clipboard

反序列化json的时候,会将数组自动转成map

Open robberphex opened this issue 4 years ago • 2 comments

输入的json字符串如下:

{
    "serviceType":"dubbo",
    "types":[
        {
            "enums":[
            ],
            "typeBuilderName":"DefaultTypeBuilder",
            "type":"int",
            "items":[
            ],
            "properties":{
            }
        }
    ]
}

反序列化的类如下:

public final class MainFastJSON {

    public static class Type {
        public List<String> enums = new ArrayList<>();
        public String typeBuilderName = "";
        public String type = "";
    }

    public static class Metadata {
        public String serviceType;
        public Map<String, Type> types = new HashMap<>();
    }

    public static void main(String[] args) {
        String jsonStr="...";
        Metadata m = JSON.parseObject(jsonStr, Metadata.class);
        System.out.println("types size:" + m.types.size());
        System.out.println(JSON.toJSONString(m));
    }
}

types在输入数据中是一个数组,但是反序列化后types变成了一个size为5的map:

{
    "serviceType":"dubbo",
    "types":{
        "enums":[
        ],
        "typeBuilderName":"DefaultTypeBuilder",
        "type":"int",
        "items":[
        ],
        "properties":{
        }
    }
}

这种情况,应该抛出反序列化异常,否则会改变数据的结构,会导致后续依赖这些数据的代码出错。

完整示例代码
// MainFastJSON.java
import com.alibaba.fastjson.JSON;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public final class MainFastJSON {

    public static class Type {
        public List<String> enums = new ArrayList<>();
        public String typeBuilderName = "";
        public String type = "";
    }

    public static class Metadata {
        public String serviceType;
        public Map<String, Type> types = new HashMap<>();
    }

    public static void main(String[] args) {
        String jsonStr = "{" +
                "    \"serviceType\":\"dubbo\"," +
                "    \"types\":[" +
                "        {" +
                "            \"enums\":[" +
                "" +
                "            ]," +
                "            \"typeBuilderName\":\"DefaultTypeBuilder\"," +
                "            \"type\":\"int\"," +
                "            \"items\":[" +
                "" +
                "            ]," +
                "            \"properties\":{" +
                "" +
                "            }" +
                "        }" +
                "    ]" +
                "}";
        Metadata m = JSON.parseObject(jsonStr, Metadata.class);
        System.out.println("types size:" + m.types.size());
        System.out.println(JSON.toJSONString(m));
    }
}

robberphex avatar Feb 24 '21 08:02 robberphex

猜测本意是想作为一个 feature 引入的( 参考fastjson-1.2.32版本发布中的 Map类型的反序列化支持size为1的数组输入,比如'[{}]' #1189), 不过看起来不是一个好的feature, 引入导致了更严重的问题。

不如简单点,取消这个 feature 。

PS: 测试了一下 Jackson 与 Gson , 都没有这个 feature。

yafengstark avatar Feb 28 '21 05:02 yafengstark

bug来自MapDeserializer里面解析JSONArray的时候没限定类型,导致有下面结构的对象可以任意的被反序列化出来

{
   "key":[
    {
        "anything":"anything",
    }
]
}

限定类型之后问题就解决了.

Certseeds avatar Apr 06 '21 07:04 Certseeds