JsonGetter提供空值

时间:2018-07-16 13:01:50

标签: java json spring spring-boot resttemplate

在我的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"]>

对于此问题的任何帮助,我们将不胜感激:)

2 个答案:

答案 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;
    }

}