在我的Spring Boot应用程序中,我正在创建一个REST API,它正在调用其他一些外部REST API。我创建了User类,它是从外部API下载的Rest API接收的对象。我的用户模型看起来像:
@JsonIgnoreProperties(ignoreUnknown = true)
public class User {
private String fullName;
private String department;
@JsonGetter("fullName")
public String getFullName() {
return fullName;
}
@JsonSetter("full_name")
public void setFullName(String fullName) {
this.fullName = fullName;
}
@JsonGetter("department")
public String getDepartment() {
return department;
}
@JsonSetter("department")
public void setDepartment(String department) {
this.department = department;
}
}
我正在使用JsonGetter和JsonSetter属性,因为我希望在camelBase中返回响应中的json属性,但在外部API中给定的属性用下划线返回:API外部响应:
{
"full_name": "User A",
"department": "A",
}
我的API响应:
{
"fullName": "User A",
"department": "A",
}
在我开始创建一些Http请求测试之前,一切似乎都很好(用Postman点击我的API会给出正确的响应(。在测试中,我收到fullName属性为null的断言错误,而在poster中执行相同的请求是用正确的响应进行响应。我的测试课程:
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class HttpRequestTest {
@LocalServerPort
private int port;
@Autowired
private TestRestTemplate restTemplate;
@Test
public void shouldReturnUserFullName() throws Exception {
assertThat(this.restTemplate.getForObject("http://localhost:" + port + "/users/a",
User.class)).extracting(User::getFullName)
.contains("User A");
}
}
我的控制器方法:
@GetMapping("users/{name}")
public ResponseEntity<User> getSpecificUserByName(@PathVariable("name") String name) {
HttpHeaders headers = new HttpHeaders();
headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
headers.add(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE);
HttpEntity<?> entity = new HttpEntity<>(headers);
ResponseEntity<User> response = restTemplate.exchange(createUriString(name), HttpMethod.GET, entity, User.class);
return response;
}
测试结果:
java.lang.AssertionError:
Expecting:
<[null]>
to contain:
<["User A"]>
but could not find:
<["User A"]>
我将感谢任何关于这个问题的帮助:(
@JsonSetter("full_name")
希望您的API响应在取消序列化期间包含属性full_name
。由于@JsonGetter("fullName")
将full_name
转换为fullName
,所以从不设置字段private String fullName;
。
您应该将@JsonSetter("full_name")
更改为@JsonSetter("fullName")
。
让我们举一个的例子
假设您的REST API返回到用户对象类以下
User reponse = new User();
response.setFullName("User A");
response.setDepartment("A");
因此,当我们调用REST API时,JSON响应如下所示
{
"fullName":"User A",
"department":"A"
}
现在,当您传递此JSON以转换为User类时,Jackson将查找名称为setFullName和setDepartment的方法。
在您的测试用例中,类似的事情正在发生,
用于代码this.restTemplate.getForObject("http://localhost:" + port + "/users/a",User.class)
首先,它调用API以获得User对象Serialized,然后将其反序列化为User类。在反序列化时,它会查找名为
setFullName且没有任何的方法
@Setter
@JsonProperty
@JsonAlias
注释或者将寻找任何具有的setter方法
@Setter("fullName")
@JsonProperty("fullName"),
@JsonAlias("fullName")
但是在您的情况下,fullName设置器被视为
public void setFull_name(String fullName) {
this.fullName = fullname;
}
因此,找不到fullName的setter,但由于您将User类标记为
@JsonIgnoreProperties(ignoreUnknown = true)
因此,不会引发任何异常,但会忽略响应JSON的fullName,因此永远不会设置fullName,它将保持为null,并且测试用例将失败。
所以,要么改变你的测试用例,要么用标记你的setter
@JsonAlias("fullName")
注释。即,您的用户类将如下所示
@JsonIgnoreProperties(ignoreUnknown = true)
public class User {
private String fullName;
private String department;
@JsonGetter("fullName")
public String getFullName() {
return fullName;
}
@JsonAlias({"fullName","full_name"})
public void setFullName(String fullName) {
this.fullName = fullName;
}
@JsonGetter("department")
public String getDepartment() {
return department;
}
@JsonSetter("department")
public void setDepartment(String department) {
this.department = department;
}
}