消除重复的 Json 元素并检索以大写字母开头的元素名称 spring boot/java

Eliminate duplicate Json elements and retrieve element names starting with capital letters spring boot/java

我正在使用 Spring 引导和 Spring 框架开发 Rest 客户端 (spring-boot-starter-parent 2.1.6.RELEASE) 我有一个 class 代表响应对象,如下所示:

public class ValidateResponse {
    private String ResponseCode;
    private String ResponseDesc;

    //getters and setters
    //constructors using fields
    //empty constructor
}

我正在为外部 api 创建一个网络挂钩,我需要 return 一个 JSON 对象到一个特定的端点(JSON 对象属性必须以大写字母开头)。我正在从嵌套在 RequestMapping 根路径中的 PostMapping 方法调用 returning 对象:

@PostMapping("hooks/validate")
public ValidateResponse responseObj(@RequestHeader Map<String, String> headersObj) {
    ValidateResponse response = new ValidateResponse("000000", "Success");

    logger.info("Endpoint = hooks/validate | Request Headers = {}", headersObj);

    return response;

} 

但是,当我从邮递员那里到达终点时,我得到了重复的变量

{
    "ResponseCode": "000000",
    "ResponseDesc": "Success",
    "responseCode": "000000",
    "responseDesc": "Success"
}

我知道 pojo-json 转换是由 spring 处理的,但我不明白为什么转换会产生重复变量。

注意: 我知道 ResponseDescResponseCode 没有使用最好的变量命名标准 (camelCasing) 声明。

我已经做了一些挖掘并根据 Java Language Specification

An identifier is an unlimited-length sequence of Java letters and Java digits, the first of which must be a Java letter.

The "Java letters" include uppercase and lowercase ASCII Latin letters A-Z (\u0041-\u005a), and a-z (\u0061-\u007a), and, for historical reasons, the ASCII underscore (_, or \u005f) and dollar sign ($, or \u0024). The $ character should be used only in mechanically generated source code or, rarely, to access pre-existing names on legacy systems.

因此,我假设使用 Camelcase 格式定义变量在语法上是正确的 [需要对此进行说明]。

我正在考虑是否必须手动创建 JSON 对象,但我想先了解此行为的原因。任何指针表示赞赏。

public class ValidateResponse {

    @JsonProperty("ResponseDesc")
    public String responseCode;

    @JsonProperty("ResponseDesc")
    public String responseDesc;

    //getters and setters
    //constructors using fields
    //empty constructor
}

这一定能解决您的问题,但我不知道原因,因为它需要 Jackson 进行深入调查。

编辑

我找到原因了。 该字段重复了,因为在你的情况下你有:

  • 2 public 字段以大写命名 -> 它们将由 jackson
  • 处理
  • 2 getters getResponseCodegetResponseDesc -> 它们将被解决 相应地作为属性 responseCoderesponseDesc 的访问器。

总而言之 - 您有 4 个属性由 Jackson 解决。只需将您的字段设为私有即可解决您的问题,但我仍然建议使用 JsonProperty 方法。

我在项目 pom.xml 文件中添加了一个 com.google.code.gson 依赖项来配置 Spring Boot 以使用 Gson(而不是默认的 jackson)。

hooks/validate 端点返回的 Json object 的 属性 名称必须以大写字母开头。使用 java class 生成响应 object 结果是 camelCased 属性 名称,所以我决定创建 JSON 响应 object 手动。这是创建自定义 JSON object:

的代码
public ResponseEntity<String> responseObj(@RequestHeader Map<String, String> headersObj) {

    HttpHeaders responseHeaders = new HttpHeaders();
    responseHeaders.setContentType(MediaType.APPLICATION_JSON);

    JsonObject response = new JsonObject();
    response.addProperty("ResponseCode", "00000000");
    response.addProperty("ResponseDesc" , "Success");

    logger.info("Endpoint = hooks/validate | Request Headers = {}", headersObj);

    return ResponseEntity.ok().headers(responseHeaders).body(response.toString());

}

注意 JSON object 作为 String 返回,因此端点的响应必须有一个额外的 header定义MediaType通知调用系统响应是JSON格式:

    responseHeaders.setContentType(MediaType.APPLICATION_JSON); 

然后将 header 添加到响应中:

    return ResponseEntity.ok().headers(responseHeaders).body(response.toString());

Jackson 反序列化它遇到的所有 public 字段。但是,如果您希望 Jackson 到 return 预期元素名称中的响应(在您的情况下元素以大写字母开头),请将字段设为 private 并用 [=14= 注释它们].您的 class 文件通常如下所示

public class ValidateResponse {

    @JsonProperty("ResponseDesc")
    private String responseCode;

    @JsonProperty("ResponseDesc")
    private String responseDesc;

    //getters and setters
    //constructors using fields
    //empty constructor
}

Note: The getters and setters for these fields should be public, otherwise Jackson won't see anything to deserialize in the class.