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

Posted

技术标签:

【中文标题】消除重复的Json元素并检索以大写字母开头的元素名称spring boot/java【英文标题】:Eliminate duplicate Json elements and retrieve element names starting with capital letters spring boot/java 【发布时间】:2019-12-01 10:42:58 【问题描述】:

我正在使用 Spring Boot 和 Spring Framework (spring-boot-starter-parent 2.1.6.RELEASE) 开发一个 Rest Client 我有一个代表响应对象的类,如下所示:

public class ValidateResponse 
    private String ResponseCode;
    private String ResponseDesc;

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

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

@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做了一些挖掘工作

标识符是 Java 字母和 Java 数字的无限长度序列,其中第一个必须是 Java 字母。

“Java 字母”包括大写和小写 ASCII 拉丁字母 AZ (\u0041-\u005a) 和 az (\u0061-\u007a),以及由于历史原因,ASCII 下划线(_ 或 \u005f)和美元符号($,或 \u0024)。 $ 字符应仅用于机械生成的源代码中,或者很少用于访问遗留系统上预先存在的名称。

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

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

【问题讨论】:

【参考方案1】:

Jackson 反序列化它遇到的所有公共字段。但是,如果您希望 Jackson 以您预期的元素名称返回响应(在您的 case 元素以大写字母开头),请创建字段 private 并使用 @JsonProperty(expected_name_here) 注释它们。您的类文件通常如下所示

public class ValidateResponse 

    @JsonProperty("ResponseDesc")
    private String responseCode;

    @JsonProperty("ResponseDesc")
    private String responseDesc;

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

注意:这些字段的 getter 和 setter 应该是 public,否则 Jackson 将在类中看不到任何要反序列化的内容。

【讨论】:

我在没有 (expected_name) 值的字段上方使用 @JsonProperty 注释。将值添加到注释可以解决问题 但是,如果您确实公开了这些字段,那么 getter 和 setter 的意义何在? 我已将字段设置为私有【参考方案2】:
public class ValidateResponse 

    @JsonProperty("ResponseDesc")
    public String responseCode;

    @JsonProperty("ResponseDesc")
    public String responseDesc;

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

这必须解决您的问题,但我不知道原因,因为它需要深入杰克逊调查。

编辑

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

2 个以大写字母命名的公共字段 -> 它们将由 jackson 处理 2 个吸气剂 getResponseCodegetResponseDesc -> 他们将被解决 相应地作为属性 responseCoderesponseDesc 的访问器。

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

【讨论】:

我为ResponseCodeResponseDesc 创建了访问器,专门返回ResponseCodeResponseDesc,但Jackson 解析了额外的responseDescresponseCode 字段。 在字段上方添加@JsonProperty注解并将("property_name")值添加到注解中解决了! @JuneM3ta 在任何情况下我都会将字段本身设为私有,因为否则不需要创建访问器 我已将字段设置为私有【参考方案3】:

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

hooks/validate 端点返回的 Json 对象的属性名称必须以大写字母开头。使用 java 类生成响应对象会导致 camelCased 属性名称,因此我决定手动创建 JSON 响应对象。下面是创建自定义 JSON 对象的代码:

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 对象以 String 的形式返回,因此来自端点的响应必须有一个额外的标头来定义 MediaType 以通知调用系统响应是 JSON 格式:

    responseHeaders.setContentType(MediaType.APPLICATION_JSON); 

然后将标头添加到响应中:

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

【讨论】:

以上是关于消除重复的Json元素并检索以大写字母开头的元素名称spring boot/java的主要内容,如果未能解决你的问题,请参考以下文章

网易2017春招笔试真题编程题集合——消除重复元素

自闭元素的另一种说法是啥(2个词)(第一个字母以e开头)

如何在颤动中检索json数据元素以列出view.builder?

perl 第六弹 变量 II

1. 从表Student中检索学生所在班级号,并消除重复行。 2. 查询课程名称中含有“技术”两个字的课程的全名

解析 Json 数据字符串并检索元素