alibaba / fastjson2

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

[BUG] FastJsonHttpMessageConverter 注册在Feign中的解码器Filter未正常执行 #2985

Open maacsek opened 1 month ago

maacsek commented 1 month ago

问题描述

使用FastJsonHttpMessageConverter作为Feign反序列化处理器,并注册几个demo ReadFilter,发现其未正常运行。

本意是想通过ReadFilter来干涉反序列化行为,然后自定义解析枚举类型的序列化json格式,例如 {"code":"MAN"} 转成 一个Sex的枚举类型。

环境信息

重现步骤

  1. 向Feign注册Fastjson解码器
    @Bean
    public Decoder decoder(@Autowired MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter, @Autowired(required = false) FastJsonHttpMessageConverter fastJsonHttpMessageConverter) {
        MappingJackson2HttpMessageConverter jackson = HttpMessageConverterClone.cloneMappingJackson2HttpMessageConverter(mappingJackson2HttpMessageConverter);
        jackson.getObjectMapper().registerModule(new JacksonEnumDeserializer());
        if (feignProperties.getHttpJsonConverter() == HttpJsonConverter.JACKSON) {
            return new SpringDecoder(() -> new HttpMessageConverters(jackson), new EmptyObjectProvider<>());
        } else {
            if (fastJsonHttpMessageConverter == null) {
                return new SpringDecoder(() -> new HttpMessageConverters(jackson), new EmptyObjectProvider<>());
            } else {
                FastJsonHttpMessageConverter httpMessageConverter = new FastJsonHttpMessageConverter();
                FastJsonConfig config = new FastJsonConfig();
                config.setReaderFilters((ContextValueFilter) (BeanContext context, Object object, String name, Object value) -> {
                    System.out.println("------------------" + name);
                    return "";
                }, (PropertyPreFilter) (context, object, name) -> {
                    System.out.println("------------------" + name);
                    return true;
                }, (ValueFilter) (object, name, value) -> {
                    System.out.println("------------------" + name);
                    return null;
                });
                return new SpringDecoder(() -> new HttpMessageConverters(httpMessageConverter), new EmptyObjectProvider<>());
            }
        }
    }
  1. 出现异常

  2. 原因是因为默认情况下,Fastjson没有办法反序列化枚举按照@JsonFormat(shape = JsonFormat.Shape.OBJECT)序列化的格式,所以看了下FastConfig只能通过自定Filter的操作空间,但是尝试注册几个ReadFilter后,它并未按预期执行。

期待的正确结果

可以输出我定义的Filter的System.out

相关日志输出

feign.codec.DecodeException: Error while extracting response for type [xx.RestResult<xx.AuthorityAccount>] and content type [application/json;charset=UTF-8]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: illegal fieldName input123, offset 138, character {, line 1, column 138, fastjson-version 2.0.52 {"data":{"account":"root-of-admin","email":null,"extInfo":null,"identifierNo":"f4a81dd14315dabd6a98f9f7342b2113","phone":null,"platform":{"desc":"管理平台","enum":"ADMIN","value":"ADMIN"},"role":{"code":"SYSTEM_ADMIN","name":"系统管理员"},"status":{"desc":"正常","enum":"NORMAL","value":"NORMAL"}},"status":{"bizErrorCode":null,"bizErrorMessage":null,"statusCode":200,"statusMessage":"Request Success","timestamp":1727266416499}}; nested exception is com.alibaba.fastjson2.JSONException: illegal fieldName input123, offset 138, character {, line 1, column 138, fastjson-version 2.0.52 {"data":{"account":"root-of-admin","email":null,"extInfo":null,"identifierNo":"f4a81dd14315dabd6a98f9f7342b2113","phone":null,"platform":{"desc":"管理平台","enum":"ADMIN","value":"ADMIN"},"role":{"code":"SYSTEM_ADMIN","name":"系统管理员"},"status":{"desc":"正常","enum":"NORMAL","value":"NORMAL"}},"status":{"bizErrorCode":null,"bizErrorMessage":null,"statusCode":200,"statusMessage":"Request Success","timestamp":1727266416499}}
    at feign.InvocationContext.proceed(InvocationContext.java:40) ~[feign-core-11.10.jar:na]
    at feign.AsyncResponseHandler.decode(AsyncResponseHandler.java:116) ~[feign-core-11.10.jar:na]
    at feign.AsyncResponseHandler.handleResponse(AsyncResponseHandler.java:89) ~[feign-core-11.10.jar:na]
    at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:141) ~[feign-core-11.10.jar:na]
    at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:91) ~[feign-core-11.10.jar:na]
    at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:100) ~[feign-core-11.10.jar:na]
    at org.springframework.cloud.openfeign.FeignCachingInvocationHandlerFactory$1.proceed(FeignCachingInvocationHandlerFactory.java:66) ~[spring-cloud-openfeign-core-3.1.5.jar:3.1.5]
    at org.springframework.cache.interceptor.CacheInterceptor.lambda$invoke$0(CacheInterceptor.java:54) ~[spring-context-5.3.31.jar:5.3.31]
    at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:351) ~[spring-context-5.3.31.jar:5.3.31]
    at org.springframework.cache.interceptor.CacheInterceptor.invoke(CacheInterceptor.java:64) ~[spring-context-5.3.31.jar:5.3.31]
    at org.springframework.cloud.openfeign.FeignCachingInvocationHandlerFactory.lambda$create$1(FeignCachingInvocationHandlerFactory.java:53) ~[spring-cloud-openfeign-core-3.1.5.jar:3.1.5]
    at com.sun.proxy.$Proxy138.fetchAccount(Unknown Source) ~[na:na]

附加信息