Skip to content

[BUG]配置Enum基于其中一个字段序列化和反序列化时,query参数无法基于其中一个字段反序列化. #1578

@fanyawei

Description

@fanyawei

问题描述

简要描述您碰到的问题。
在枚举的某个字段中加入了@JSONField(value = true)注解,序列化没问题,但反序列华的时候,只能序列化@RequestBody的参数类型,query参数 (示例:http://127.0.0.1:8080/demo/get?name=张三丰&gender=1) 无法反序列化。

环境信息

请填写以下信息:

  • OS信息: [e.g.:Windows 11 家庭中文版 22H2]
  • JDK信息: [e.g.:OracleJdk-20.0.1]
  • 版本信息:[e.g.:Fastjson2 2.0.33]

重现步骤

如何操作可以重现该问题:
1、引入fastjson2的spring依赖包,测试工程的pom.xml文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>3.1.0</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.example</groupId>
	<artifactId>demo</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>demo</name>
	<description>Demo project for Spring Boot</description>
	<properties>
		<java.version>20</java.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<scope>runtime</scope>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-configuration-processor</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>com.alibaba.fastjson2</groupId>
			<artifactId>fastjson2-extension-spring6</artifactId>
			<version>2.0.33</version>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
				<configuration>
					<excludes>
						<exclude>
							<groupId>org.projectlombok</groupId>
							<artifactId>lombok</artifactId>
						</exclude>
					</excludes>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

2、编写枚举和测试用的model类
枚举代码如下:

package com.example.demo.model;

import com.alibaba.fastjson2.annotation.JSONField;

import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public enum GenderEnum {
	UNKNOWN(0, "未知"),
	MALE(1, "男"),
	FEMALE(2, "女");

	@JSONField(value = true)
	private final Integer code;
	private final String name;
}

测试的model代码如下:

package com.example.demo.model;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@Getter
@Setter
@ToString
public class User {
	private String name;
	private GenderEnum gender;
}

3、编写测试的Controller

package com.example.demo.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.example.demo.model.User;

@RestController
@RequestMapping("/demo")
public class DemoController {
	private static final Logger logger = LoggerFactory.getLogger(DemoController.class);

	@GetMapping("/get")
	public User get(User user) {
		logger.info("get请求获取到的参数信息:\n{}", user);
		return user;
	}

	@PostMapping("/post")
	public User post(@RequestBody User user) {
		logger.info("post请求获取到的参数信息:\n{}", user);
		return user;
	}
}

4、通过启动服务,并通过postman提交请求,观察参数输出。

期待的正确结果

不论请求是通过GET提交还是POST提交,又或者更多的方式提交。不论传的参数是query参数还是body参数,都能正确地反序列化

相关日志输出

GET请求中,通过枚举某一字段(这里是code)的值传参时的日志输出(不正常):

2023-06-17T00:17:30.842+08:00    [0;39m     [33m WARN    [0;39m     [35m14224    [0;39m     ---    [0;39m     [nio-8080-exec-2]    [0;39m     [36m.w.s.m.s.DefaultHandlerExceptionResolver    [0;39m     :    [0;39m Resolved [org.springframework.web.bind.MethodArgumentNotValidException: Validation failed for argument [0] in public com.example.demo.model.User com.example.demo.controller.DemoController.get(com.example.demo.model.User): [Field error in object 'user' on field 'gender': rejected value [1]; codes [typeMismatch.user.gender,typeMismatch.gender,typeMismatch.com.example.demo.model.GenderEnum,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [user.gender,gender]; arguments []; default message [gender]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'com.example.demo.model.GenderEnum' for property 'gender'; Failed to convert from type [java.lang.String] to type [com.example.demo.model.GenderEnum] for value [1]]] ]

GET请求中,通过枚举名称传参时的日志输出(正常):

2023-06-17T00:22:11.845+08:00    [0;39m     [32m INFO    [0;39m     [35m14224    [0;39m ---    [0;39m [nio-8080-exec-4]    [0;39m     [36mc.e.demo.controller.DemoController          [0;39m :    [0;39m get请求获取到的参数信息:
User(name=张三丰, gender=MALE)

POST请求的日志输出(正常):

2023-06-17T00:14:04.408+08:00    [0;39m     [32m INFO    [0;39m     [35m14224    [0;39m     ---    [0;39m     [nio-8080-exec-1]    [0;39m     [36mo.a.c.c.C.[Tomcat].[localhost].[/]          [0;39m     :    [0;39m Initializing Spring DispatcherServlet 'dispatcherServlet'
2023-06-17T00:14:04.408+08:00    [0;39m     [32m INFO    [0;39m     [35m14224    [0;39m     ---    [0;39m     [nio-8080-exec-1]    [0;39m     [36mo.s.web.servlet.DispatcherServlet           [0;39m     :    [0;39m Initializing Servlet 'dispatcherServlet'
2023-06-17T00:14:04.412+08:00    [0;39m     [32m INFO    [0;39m     [35m14224    [0;39m     ---    [0;39m     [nio-8080-exec-1]    [0;39m     [36mo.s.web.servlet.DispatcherServlet           [0;39m     :    [0;39m Completed initialization in 3 ms
2023-06-17T00:14:04.797+08:00    [0;39m     [32m INFO    [0;39m     [35m14224    [0;39m     ---    [0;39m     [nio-8080-exec-1]    [0;39m     [36mc.e.demo.controller.DemoController          [0;39m     :    [0;39m post请求获取到的参数信息:
User(name=张三丰, gender=MALE)

附加信息

以下是提交请求时候的Postman工具截图
GET请求中,通过枚举某一字段(这里是code)的值传参时的截图(不正常):
image

GET请求中,通过枚举名称传参时的截图(正常):
image

POST请求的截图(正常):
image

其他测试

不通过springmvc,直接反序列化测试,Java代码如下:

package com.example.demo;

import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson2.JSON;
import com.example.demo.model.User;

class FastjsonTest {

	private static final Logger logger = LoggerFactory.getLogger(FastjsonTest.class);

	@Test
	void test() {
		// json串,gender为整数型
		String text = """
				{
					"name":"张三丰",
					"gender":1
				}
				""";
		logger.info("gender为整数型时的,用户对象:\n{}", JSON.parseObject(text, User.class));

		// json串,gender为字符串
		text = """
				{
					"name":"张三丰",
					"gender":"1"
				}
				""";
		logger.info("gender为字符串时的用户对象:\n{}", JSON.parseObject(text, User.class));
	}
}

输出的日志如下(第一个正常,第二个不正常,如果是jackson则两个都正常,当然,这个不算太重要):

00:29:31.785 [main] INFO com.example.demo.FastjsonTest -- gender为整数型时的,用户对象:
User(name=张三丰, gender=MALE)
00:29:31.788 [main] INFO com.example.demo.FastjsonTest -- gender为字符串时的用户对象:
User(name=张三丰, gender=null)

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingfixed

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions