在我的Spring Boot应用程序中,我正在创建一个REST API,它正在调用其他一些外部REST API。我创建了User类,该类是我的Rest API从外部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属性,因为我希望在camelCase中返回我的json属性作为响应,但是在外部API中给定的属性以下划线返回: 外部API响应:
{
"full_name": "User A",
"department": "A",
}
我的API响应:
{
"fullName": "User A",
"department": "A",
}
直到我开始创建一些Http请求测试之前,一切似乎都工作正常(用Postman打入我的API会给出正确的响应)。在测试中,我收到断言错误,即fullName属性为null,而在邮递员中执行相同的请求则以正确的响应进行响应。 我的测试课:
@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"]>
对于此问题的任何帮助,我们将不胜感激:)
答案 0 :(得分:1)
@JsonSetter("full_name")
希望您的API响应在反序列化期间包含属性full_name
。由于@JsonGetter("fullName")
将full_name
转换为fullName
,所以永远不会设置字段private String fullName;
。
您应将@JsonSetter("full_name")
更改为@JsonSetter("fullName")
。
答案 1 :(得分:0)
让我们举个例子
假设您的REST API在User类的Object之下返回
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 对象序列化,然后将其反序列化为 User 类。反序列化时,它将查找名为
的方法
setFullName ,不包含任何
@Setter
@JsonProperty
@JsonAlias
注释 或将使用
查找任何设置方法@Setter("fullName")
@JsonProperty("fullName"),
@JsonAlias("fullName")
但是在您的情况下,全名设置器被视为
public void setFull_name(String fullName) {
this.fullName = fullname;
}
因此,找不到全名的setter,但由于您将 User 类标记为
@JsonIgnoreProperties(ignoreUnknown = true)
因此不会引发任何异常,但是会忽略您的Response JSON的 fullName ,因此将永远不会设置fullName,它保持为空,并且测试用例失败。
因此,更改测试用例或用
标记您的设置者@JsonAlias("fullName")
注释。 即您的User类如下所示
@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;
}
}