SpringBoot:为缺少某些字段的JSON请求提供服务

huangapple go评论110阅读模式
英文:

SpringBoot: Serving JSON requests with some fields missing

问题

  1. 我正在构建一个POJO以匹配在基于SpringBoot实现的REST API中收到的一些请求其中一些数据**必须**由客户端提供给我否则我甚至不愿意处理该请求为了确保客户端至少提供给我我**绝对**需要的内容我使用了Lombok`@NonNull`注解
  2. ```java
  3. @Data
  4. public class ProductRequestBody implements Serializable
  5. {
  6. private String name;
  7. private String category;
  8. private String description;
  9. private String abbreviation;
  10. private String labelColor;
  11. private Double cost;
  12. public ProductRequestBody()
  13. {
  14. }
  15. @JsonCreator
  16. public ProductRequestBody(@NonNull @JsonProperty("name") String name,
  17. @NonNull @JsonProperty("category") String category,
  18. @JsonProperty("description") String description,
  19. @NonNull @JsonProperty("cost") Double cost)
  20. {
  21. this.name = name;
  22. this.category = category;
  23. this.description = description;
  24. this.cost = cost;
  25. }
  26. }

(我完全理解将货币数量处理为Double是不推荐的;这只是一个示例。)

从控制器处理这个类就像是在/products端点上添加一个监听器一样简单:

  1. @PostMapping(value = "/products")
  2. public Product postProduct(@RequestBody ProductRequestBody newProduct)
  3. {
  4. // ...
  5. // 适当地处理请求
  6. // ...
  7. }

现在,如果我收到一个POST请求,其中一个未被标记为@NonNull的字段为null,就像下面这样,我可以毫无问题地处理它:

  1. {
  2. "name": "Some Product Name",
  3. "category": "Some Product Category",
  4. "cost" : 10.0,
  5. "description": null
  6. }

然而,我的目标是能够处理那些根本不关心某些字段的JSON请求。也就是说,我希能够处理以下情况,但目前还无法做到:

  1. {
  2. "name": "Some Product Name",
  3. "category": "Some Product Category",
  4. "cost" : 10.0,
  5. // 这个载荷中没有"description"字段
  6. }

我该如何实现这一点?代码越少越好,一如既往。

  1. <details>
  2. <summary>英文:</summary>
  3. I&#39;m building a POJO class to match some requests coming my way in a REST API implemented on SpringBoot. Some of the data _has_ to be given to me, otherwise I am not willing to even serve the request. To make sure the client gives me at least what I _absolutely_ need, I have used Lombok&#39;s `@NonNull`:
  4. ```java
  5. @Data
  6. public class ProductRequestBody implements Serializable
  7. {
  8. private String name;
  9. private String category;
  10. private String description;
  11. private String abbreviation;
  12. private String labelColor;
  13. private Double cost;
  14. public ProductRequestBody()
  15. {
  16. }
  17. @JsonCreator
  18. public ProductRequestBody(@NonNull @JsonProperty(&quot;name&quot;) String name,
  19. @NonNull @JsonProperty(&quot;category&quot;) String category,
  20. @JsonProperty(&quot;description&quot;) String description,
  21. @NonNull @JsonProperty(&quot;cost&quot;) Double cost)
  22. {
  23. this.name = name;
  24. this.category = category;
  25. this.description = description;
  26. this.cost = cost;
  27. }
  28. }

(I completely understand that handling monetary quantities as Doubles is a no-no; this is just an example.

Processing this from my controller is as easy as a listener on the /products endpoint like so:

  1. @PostMapping(value = &quot;/products&quot;)
  2. public Product postProduct(@RequestBody ProductRequestBody newProduct)
  3. {
  4. // ...
  5. // Serve the request appropriately
  6. // ...
  7. }

Now, if I receive a POST request with a null field that has not been marked as @NonNull, like the following, I can serve it without issue:

  1. {
  2. &quot;name&quot;: &quot;Some Product Name&quot;,
  3. &quot;category&quot;: &quot;Some Product Category&quot;,
  4. &quot;cost&quot; : 10.0,
  5. &quot;description&quot;: null
  6. }

My goal, however, is to be able to handle JSON requests that simply don't even have the fields they don't care about. That is, I want to be able to serve the following as well, and I currently can't:

  1. {
  2. &quot;name&quot;: &quot;Some Product Name&quot;,
  3. &quot;category&quot;: &quot;Some Product Category&quot;,
  4. &quot;cost&quot; : 10.0,
  5. // No &quot;description&quot; field in this payload
  6. }

How could I go about doing this? The less code, the better, as always.

答案1

得分: 2

  1. 如果您使用spring-bootlombok您可以将您的类简化为以下形式
  2. @Data
  3. public class ProductRequestBody implements Serializable {
  4. @NonNull
  5. private String name;
  6. @NonNull
  7. private String category;
  8. @NonNull
  9. private Double cost;
  10. private String description;
  11. private String abbreviation;
  12. private String labelColor;
  13. }
  14. 如果没有提供namecategorycost则会返回400否则返回200
英文:

If you use spring-boot and lombok you can simplify your class to be like this:

  1. @Data
  2. public class ProductRequestBody implements Serializable {
  3. @NonNull
  4. private String name;
  5. @NonNull
  6. private String category;
  7. @NonNull
  8. private Double cost;
  9. private String description;
  10. private String abbreviation;
  11. private String labelColor;
  12. }

it will return 400 if name, category or cost will be not provided and 200 otherwise.

答案2

得分: 1

Spring可以处理JSON的序列化和反序列化而不会出现任何问题。
你应该让Spring来处理它。
你可以尝试以下内容。

  1. @Data
  2. public class ProductRequestBody implements Serializable {
  3. @NonNull
  4. private String name;
  5. @NonNull
  6. private String category;
  7. private String description;
  8. private String abbreviation;
  9. private String labelColor;
  10. @NonNull
  11. private Double cost;
  12. }

如果你真的想要遵循创建构造函数的模式,那么你应该创建一个只包含@NonNull字段的构造函数,并为其他字段创建getter(lombok会为你处理)。如果你想要添加@JsonProperty,那么你需要创建一个单独的getter方法。

  1. @Data
  2. public class ProductRequestBody implements Serializable
  3. {
  4. private String name;
  5. private String category;
  6. private String description;
  7. private String abbreviation;
  8. private String labelColor;
  9. private Double cost;
  10. public ProductRequestBody()
  11. {
  12. }
  13. @JsonCreator
  14. public ProductRequestBody(@NonNull @JsonProperty("name") String name,
  15. @NonNull @JsonProperty("category") String category,
  16. @NonNull @JsonProperty("cost") Double cost)
  17. {
  18. this.name = name;
  19. this.category = category;
  20. this.cost = cost;
  21. }
  22. @JsonProperty("description")
  23. public String getDescription() {
  24. return description;
  25. }
  26. }
英文:

Spring handles serializing and deserializing json without any issue.
You should let spring handle it.
You can try the following.

  1. @Data
  2. public class ProductRequestBody implements Serializable {
  3. @NonNull
  4. private String name;
  5. @NonNull
  6. private String category;
  7. private String description;
  8. private String abbreviation;
  9. private String labelColor;
  10. @NonNull
  11. private Double cost;
  12. }

If you really want to follow the pattern of creating a constructor, then you should create a constructor with only the @NonNull fields and create getter of others (lombok handles that for you). If you want to add @JsonProperty then you need to create separate getter.

  1. @Data
  2. public class ProductRequestBody implements Serializable
  3. {
  4. private String name;
  5. private String category;
  6. private String description;
  7. private String abbreviation;
  8. private String labelColor;
  9. private Double cost;
  10. public ProductRequestBody()
  11. {
  12. }
  13. @JsonCreator
  14. public ProductRequestBody(@NonNull @JsonProperty(&quot;name&quot;) String name,
  15. @NonNull @JsonProperty(&quot;category&quot;) String category,
  16. @NonNull @JsonProperty(&quot;cost&quot;) Double cost)
  17. {
  18. this.name = name;
  19. this.category = category;
  20. this.cost = cost;
  21. }
  22. @JsonProperty(&quot;description&quot;)
  23. public String getDescription() {
  24. return description;
  25. }
  26. }

huangapple
  • 本文由 发表于 2020年10月13日 00:52:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/64322038.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定