alibaba / fastjson2

🚄 FASTJSON2 is a Java JSON library with excellent performance.
Apache License 2.0
3.82k stars 499 forks source link

[BUG] Deserialization with SupportAutoType #2561

Closed Cooper-Zhong closed 6 months ago

Cooper-Zhong commented 6 months ago

问题描述

Fastjson使用SupportAutoType反序列化属性缺失,考虑到autotype的历史,不确定是否为bug。

环境信息

重现步骤

Fastjson2:

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSONReader;
import com.alibaba.fastjson2.JSONWriter;
import com.alibaba.fastjson2.annotation.JSONType;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

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

import static org.junit.Assert.assertEquals;

public class MutatedIssue1769_fj2 {
    static BirtneyModel sourceModel = new BirtneyModel();

    @BeforeAll
    public static void setUp() {
        AlimeFromConfig alimeFromConfig = new AlimeFromConfig();
        alimeFromConfig.setDefaultFromId("birtney");

        List<AbstractConfig> sourceConfigs = new ArrayList<>();
        sourceConfigs.add(alimeFromConfig);
        Map<String, List<AbstractConfig>> configMap = new HashMap<>();
        configMap.put("FROM", sourceConfigs);

        sourceModel.setConfigs(configMap);
    }

    @Test
    public void testOnInvokeJsonGenericParse2() {

        String json = JSON.toJSONString(sourceModel, JSONWriter.Feature.WriteClassName);
        System.out.println(json);

        BirtneyModel birtneyModel =
                JSONObject.parseObject(json, BirtneyModel.class, JSONReader.Feature.SupportAutoType);

        System.out.println(birtneyModel);
        assertEquals(
                AlimeFromConfig.class,
                birtneyModel.configs.get("FROM").get(0).getClass()
        );
    }

    @Data
    @EqualsAndHashCode(callSuper = true)
    public static class AlimeFromConfig
            extends AbstractConfig {
        private String defaultFromId;
        private Map<String, String> urlMap;
    }

    @JSONType(builder = AlimeFromConfig.class)
    public abstract static class AbstractConfig
            implements Serializable {
        private Long id;
        private String type;
        private String subType;
        private String sceneId;
        private Integer version;
    }

    @Data
    public static class BirtneyModel
            implements Serializable {
        private Map<String, List<AbstractConfig>> configs;
    }
}

Fastjson:

import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.annotation.JSONType;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

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

import static org.junit.Assert.assertEquals;

public class MutatedIssue1769_fj {
    static BirtneyModel sourceModel = new BirtneyModel();

    @BeforeAll
    public static void setUp() {
        AlimeFromConfig alimeFromConfig = new AlimeFromConfig();
        alimeFromConfig.setDefaultFromId("birtney");

        List<AbstractConfig> sourceConfigs = new ArrayList<>();
        sourceConfigs.add(alimeFromConfig);
        Map<String, List<AbstractConfig>> configMap = new HashMap<>();
        configMap.put("FROM", sourceConfigs);

        sourceModel.setConfigs(configMap);
    }

    @Test
    public void testOnInvokeJsonGenericParse() {
        ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
        String json = JSON.toJSONString(sourceModel,  SerializerFeature.WriteClassName);
        System.out.println(json);

        BirtneyModel birtneyModel =
                JSONObject.parseObject(json, BirtneyModel.class, Feature.SupportAutoType);

        System.out.println(birtneyModel);
        assertEquals(
                AlimeFromConfig.class,
                birtneyModel.configs.get("FROM").get(0).getClass()
        );
    }

    @Data
    @EqualsAndHashCode(callSuper = true)
    public static class AlimeFromConfig
            extends AbstractConfig {
        private String defaultFromId;
        private Map<String, String> urlMap;
    }

    @JSONType(builder = AlimeFromConfig.class)
    public abstract static class AbstractConfig
            implements Serializable {
        private Long id;
        private String type;
        private String subType;
        private String sceneId;
        private Integer version;
    }

    @Data
    public static class BirtneyModel
            implements Serializable {
        private Map<String, List<AbstractConfig>> configs;
    }
}

期待的正确结果

Fastjson2: MutatedIssue1769_fj2.BirtneyModel(configs={FROM=[MutatedIssue1769_fj2.AlimeFromConfig(defaultFromId=birtney, urlMap=null)]})

Fastjson: MutatedIssue1769_fj.BirtneyModel(configs={})

wenshao commented 6 months ago

兼容API的SupportAutoType问题不修了