alibaba / alibaba/fastjson2

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

Open
#2,985 1 comment 0 reactions 0 assignees View on GitHub
bug
Dominant language
Java
Stars
4.4k
Forks
613
Avg merge
1d 22h
Merged PRs (30d)
6

Description

### 问题描述

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

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

### 环境信息

- OS信息: [ Darwin M2 16GB]
- JDK信息: [java 11.0.22 2024-01-16 LTS]
- 版本信息:[Fastjson2 2.0.53]

### 重现步骤

1. 向Feign注册Fastjson解码器

```java
@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<>());
}
}
}
```
2. 出现异常

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

### 期待的正确结果

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

### 相关日志输出
```
feign.codec.DecodeException: Error while extracting response for type [xx.RestResult] 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]
```

#### 附加信息

Contributor guide

Open the contributing guide

Research direction

Start with the Feign decoder bean that creates FastJsonHttpMessageConverter and calls FastJsonConfig.setReaderFilters, then trace how the converter handles the response body. Done means the registered ReadFilters execute during Feign response deserialization and the enum-shaped response no longer produces the reported parse error.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
api, backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.