【问题标题】:Accessing dynamically added properties in Spring @RequestBody在 Spring @RequestBody 中访问动态添加的属性
【发布时间】:2019-10-23 07:02:50
【问题描述】:

我有一个如下的帖子映射:

@PostMapping(value = "/profiles/{profileId}/verify/")
public Response getVerificationInformation (
    @RequestBody VerificationBody body) {
    ... do something with the body
    ... call function A with body object
}

稍后在函数 A 中,我正在访问 body 对象以获取一些属性。

另外,在前端,我正在修改命中此帖子映射的 JSON 对象(我正在添加另一个属性)。

例如,

{
    "name" : "Example",
    "profileId" : "123",
    // and I am dynamically adding an attribute 'country'
    "country" : "US"
}

问题在于函数 A,我无法获取有关动态添加的属性(在本例中为“国家”)的信息。

为动态添加的属性声明 getter 并不理想,因为有很多属性是动态添加的。

我已经尝试了 @JsonAnySetter 和 @JsonAnyGetter 的方向,但我得到了 400。我正在寻找其他解决方案。

请帮助并提前感谢您! (我简化了一些变量和函数的名称,但我希望它不会太难理解。


VerificationBody 可以认为如下:

public class VerificationBody {
    @JsonProperty(value = "name")
    String name,
    @JsonProperty(value = "profileId")
    Long profileId,
    // ... it does not include country
}

设法解决了 400 问题,我能够通过 JsonAnyGetter 和 JsonAnySetter 获取属性。

【问题讨论】:

  • 如果是这样,为什么不使用Map 代替RequestBody
  • VerificationBody 里面有什么?请分享课程。
  • @Prashant 我正在做一个相当大的项目,我非常不愿意更改请求正文类型,因为这将是一个很大的重构。
  • @VinayPrajapati 回答了这个问题
  • “我在@JsonAnySetter@JsonAnyGetter的方向上尝试了一些东西,但我得到了400”然后弄清楚为什么你会得到400,因为@987654329 @ 和 @JsonAnyGetter正确答案。查看导致 400 的错误的堆栈跟踪。

标签: java json spring jackson


【解决方案1】:

您的VerificationBody 类可能如下所示:

class VerificationBody {
private String prop1;
//other properties & their getters and setter

private Map<String, ? extends Object> otherProps;
// getter setters for  otherProps

}

这将允许您始终接收其他属性,而不会出现任何扩展问题。

【讨论】:

  • 不幸的是,在前端修改 JSON 时,我无法像 otherProps 一样将其添加到其他 Map 中,但它会像上面的示例一样简单地附加到 JSON 对象中。也许我可以改变这种行为,但我很不愿意这样做。
  • 或者你的意思是用 @JsonAnySetter 之类的东西来注释 otherProps?
【解决方案2】:

您可以使用HashMap 来解决此类问题:

@RequestMapping(value = "/profiles/{profileId}/verify/", headers = "Accept=application/json", method = RequestMethod.POST)
public void verifyBody(@RequestBody HashMap<String, HashMap<String, String>> requestData) {

HashMap<String, String> customerInfo = requestData.get("verificationBody");
String param1 = customerInfo.get("param1");
//TODO now do whatever you want to do.
}

【讨论】:

  • 感谢您的建议。但是我正在做一个相当大的项目,我非常不愿意更改请求正文类型,因为这将是一个很大的重构。
【解决方案3】:

请求正文的注解是@RequestBody。由于请求正文是一个键值对,因此将其声明为 Map 是明智的。

@PostMapping("/blog")
public Blog create(@RequestBody Map<String, String> body){...}

提取相应的键和它们的值:

String id = body.get("id");
String title = body.get("title");
String content = body.get("content");

用这个链接试试

https://medium.com/better-programming/building-a-spring-boot-rest-api-part-ii-7ff1e4384b0b

【讨论】:

  • 感谢您的建议。但是我正在做一个相当大的项目,我非常不愿意更改请求正文类型,因为这将是一个很大的重构。
【解决方案4】:

根本原因是您的 JSON 字符串无效,有效的应该如下所示:

{
  "name": "Example",
  "profileId": "123",
  "country": "US"
}

请确保每个 key 都是双引号,否则在使用 Jackson 将请求正文序列化到您的 POJO 时,您将收到 400 Bad Request。。 p>

顺便说一句,我使用的是 Spring Boot,我可以通过您的代码 sn-p 使用 invalid JSON 字符串作为有效负载重现获取 HTTP 状态代码 400。

【讨论】:

  • 对不起,我忘了放双引号。在我添加 JsonAnySetter 之前它一直在工作,所以它认为这是问题所在。将更新问题以包含双引号!谢谢。
  • @seokhoonlee 好的!但我也用有效的 JSON 字符串测试了你的代码,效果很好!因此,我无法再次重现 400 Bad Request。
  • 是的,这个项目很大,所以有很多隐藏信息层。我认为罪魁祸首是spring.jackson.deserialization.FAIL_ON_UNKNOWN_PROPERTIES=true。感谢您的探索! :)
  • @seokhoonlee 是的!将此设置添加到 application.properties 后,我现在收到 400 错误消息 - JSON 解析错误:无法识别的字段 \"country\"....
  • 是的,但遗憾的是我可能无法更改此配置,因为它会影响其他地方的 json 反序列化。所以我可能不得不看看其他解决方案。无论如何谢谢你:D
【解决方案5】:

你可以尝试像这样修改VerificationBody类:

public class VerificationBody {
    private String name;
    private Long profileId;

    // getters & setters
}

getVerificationInformation 类是这样的:

@PostMapping(value = "/profiles/{profileId}/verify/",
             consumes = MediaType.APPLICATION_JSON_VALUE,
             produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public Response getVerificationInformation (
    @RequestBody VerificationBody body) {

【讨论】:

  • 我不明白这如何解决访问动态添加的国家/地区属性的问题。
猜你喜欢
  • 1970-01-01
  • 2021-12-05
  • 1970-01-01
  • 2013-07-12
  • 2020-11-22
  • 2020-11-21
  • 1970-01-01
  • 1970-01-01
  • 2020-07-26
相关资源
最近更新 更多