SpringDoc-OpenApi與Fastjson沖突——FastJsonHttpMessageConverter對String的默認處理


我的項目中默認是這樣使用FastJsonHttpMessageConverter的:

@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter();
    FastJsonConfig fastJsonConfig = new FastJsonConfig();
    fastJsonConfig.setSerializerFeatures(
            // 防止循環引用
            SerializerFeature.DisableCircularReferenceDetect,
            // 空集合返回[],不返回null
            SerializerFeature.WriteNullListAsEmpty,
            // 空字符串返回"",不返回null
            SerializerFeature.WriteNullStringAsEmpty,
            SerializerFeature.WriteMapNullValue
    );
    fastJsonConfig.getSerializeConfig().put(String.class,MyStringSerializer.instance);
    fastJsonHttpMessageConverter.setFastJsonConfig(fastJsonConfig);
    //處理中文亂碼問題
    List<MediaType> fastMediaTypes = new ArrayList<>();
    fastMediaTypes.add(MediaType.APPLICATION_JSON);
    fastJsonHttpMessageConverter.setSupportedMediaTypes(fastMediaTypes);
    converters.add(0, fastJsonHttpMessageConverter);//放到前面

}

之前本來相安無視,后面因為springboot升級到2.6.x,原有的springfox因為很久沒有更新出現兼容問題(雖然可以解決),再加上想嘗試使用新的openapi3,因此換用了最近有在更新的springdoc-openapi。結果兩者配合使用時,swagger界面無法加載,而v3/api-docs中的json都多出了\:

"{\"openapi\":\"3.0.1\",\"info\":{\"title\":\"OpenAPI definition\",\"version\":\"v0\"},\"servers\":[{\"url\":\"http://localhost:8099\",\"description\":\"Generated server url\"}],\"paths\":{},\"components\":{}}"

這直接導致swagger無法正確的識別,從而界面加載失敗。而原來使用springfox時,並沒有出現這個問題。

經過打斷點分析,發現原來使用springfox時,傳到com.alibaba.fastjson.serializer.SerializeConfig#getObjectWriter(java.lang.Class<?>, boolean) 這里時,class是springfox.documentation.spring.web.json.Json,fastjson對此作了特殊處理,因此可以保持原樣。而改換springdoc時,此處傳入的class卻是String! 而fastjson默認會對String進行處理,加上轉義符號,因此導致最終的結果出現異常。
解決辦法:

1、換成Jackson的converter(springboot默認就是Jackson)。

2、FastJsonHttpMessageConverter:自定義一個StringSerializer,覆蓋掉fastjson的默認的StringSerializer

public class MyStringSerializer implements ObjectSerializer {
    public static final MyStringSerializer instance = new MyStringSerializer();
    @Override
    public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException {
        SerializeWriter out = serializer.getWriter();
        out.write(object.toString());
    }
}

然后在FastJsonHttpMessageConverter的配置文件中,如下使用
fastJsonConfig.getSerializeConfig().put(String.class,MyStringSerializer.instance);
即可覆蓋掉fastjson默認的StringSerializer。(也可以通過這么操作,對其它類進行自定義處理)。
因為理解不是很透徹,不清楚fastjson為什么默認要對String進行字符轉義處理,也不太清楚這樣修改是否會導致其他后果,如果不妥希望能指出。

(本bug已經提交到fastjson在github上的issues中,期望能得到解答,不過這個好像只能靠分析String里的內容來solve了...)

這個bug只有FastJsonHttpMessageConverter添加到converters最前面或在默認的Jackson之前時會引起這個問題,關於converters的順序等更深入的探討,可以參考這篇文章:

https://segmentfault.com/a/1190000012659486


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM