【问题标题】:Spring REST - binding GET parameters to list of nested objectsSpring REST - 将 GET 参数绑定到嵌套对象列表
【发布时间】:2019-12-09 20:49:11
【问题描述】:

我的问题几乎是 1:1 的 this one。我唯一的区别(和挣扎)是我的“数据容器”有一个对象集合。它看起来像这样:

public class A {
    int plainFieldA;
    B fieldB;
    List<B> collectionB = new ArrayList<>();
}

public class B {
    int plainFieldB;
}

@Transactional(readOnly = true)
@GetMapping("")
public Entity getAll(A reqParam) {
    return getAll(reqParam);
}

是否可以在不创建转换器的情况下在 url http://localhost/api/test?plainFieldA=1 的参数中定义 collectionB ? @GameSalutes 正确地指出,从春天开始 4 我们可以做 fieldB.plainFieldB=2 所以网址将是:http://localhost/api/test?plainFieldA=1&amp;fieldB.plainFieldB=2 但问题是我们可以在不创建转换器的情况下用 collectionB 做类似的事情吗?

【问题讨论】:

  • 这是个好问题。我认为这是不可能的,因为列表中的值表示存在问题。你会如何代表他们?集合B[0].plainFieldB?如果你有 100 个值?不要忘记 Get 映射依赖于 http GET 方法,并且 QueryString 的大小是有限制的。
  • 由于GET 方法的字符大小限制,我会选择在这种情况下调用POST
  • 看起来您正在尝试实现搜索以根据不同的参数搜索某些内容。如果你想实现基于不同参数的搜索,那么我会推荐你​​使用“解释器模式”而不用担心额外的处理。 en.wikipedia.org/wiki/Interpreter_pattern

标签: java spring spring-boot


【解决方案1】:

是的,您可以这样提出请求:

http://localhost/api/test?plainFieldA=1&fieldB.plainFieldB=2&collectionB[0].plainFieldB=9

或者编码请求,对于邮递员:

http://localhost/api/test?plainFieldA=1&fieldB.plainFieldB=2&collectionB%5B0%5D.plainFieldB=9

请求中有两个对象:

http://localhost/api/test?plainFieldA=1&fieldB.plainFieldB=2&collectionB%5B0%5D.plainFieldB=9&collectionB%5B1%5D.plainFieldB=11

IDE中带断点的结果:

【讨论】:

  • 哦,好吧.. 这么久我的“我认为这是不可能的”。我什至从字面上写了要使用的语法。 :D 应得的赏金,如果答案被接受!
  • 太完美了。谢谢你。我点击了赏金按钮,但它显示“你可以在 14 小时内奖励你的赏金”(并且不能转移)。所以我会在 14 小时内完成。谢谢。
  • 在根据给定条件进行搜索时,您是否推荐 POST 而不是 GET
  • 谢谢!是的,我建议在这种情况下通过 GET POST,以防您发送比简单键/值更复杂的对象。如果有一天你有一个包含许多元素的列表,GET 会给你带来问题,而且在设计级别你正在发送一个对象。
【解决方案2】:

接受的答案就像一个魅力,但如果有人达到 url 大小限制或其他原因,我会添加这个答案作为替代。

按照this thread 的建议,这就是我的做法。

  • 前端:将您的对象字符串化,然后将其编码为 base64 以进行提交。
  • 后端:解码 base64 字符串,然后将字符串 json 转换为所需的对象。

使用 postman 调试 API 并不是最好的方法,但它按我的预期工作。

原始对象: { page: 1, size: 5, filters: [{ field: "id", value: 1, comparison: "EQ" }

编码对象: eyJwYWdlIjoxLCJzaXplIjo1LCJmaWx0ZXJzIjpbeyJmaWVsZCI6ImlkUGFyZW50IiwiY29tcGFyaXNvbiI6Ik5VTEwifV19

@GetMapping
fun list(@RequestParam search: String?): ResponseEntity<ListDTO> {
    val filter: SearchFilterDTO = decodeSearchFieldDTO(search)
    ...
}

private fun decodeSearchFieldDTO(search: String?): SearchFilterDTO {
    if (search.isNullOrEmpty()) return SearchFilterDTO()
    return Gson().fromJson(String(Base64.getDecoder().decode(search)), SearchFilterDTO::class.java)
}

这里是 SearchFilterDTO 和 FilterDTO

class SearchFilterDTO(
    var currentPage: Int = 1,
    var pageSize: Int = 10,
    var sort: Sort? = null,
    var column: String? = null,
    var filters: List<FilterDTO> = ArrayList<FilterDTO>(),
    var paged: Boolean = true
)

class FilterDTO(
    var field: String,
    var value: Any,
    var comparison: Comparison
)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-11-29
    • 2019-04-01
    • 2014-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多