【问题标题】:How to use query parameter represented as JSON with Spring RestTemplate?如何在 Spring RestTemplate 中使用以 JSON 表示的查询参数?
【发布时间】:2016-04-05 10:03:49
【问题描述】:

我需要使用 Spring RestTemplate 向具有表示为 JSON 的查询参数的 HTTP 端点发出请求。

restTemplate.getForObject(
    apiRoot + "/path" + "?object={myObject}",
    Response.class,
    new MyObject())

在这里,我需要将 MyObject 转换为 JSON(显然是 URL 编码的)。但是RestTemplate 只是将其转换为String 并使用toString 调用。 MyObject 可以由 Jackson 转换为 JSON。 UriComponentsBuilder 的行为方式相同:

UriComponentsBuilder.fromHttpUrl(apiRoot)
    .path("/path")
    .queryParam("object", new MyObject()))
    .queryParam("access_token", accessToken)
    .toUri()

有没有办法避免用手打电话给ObjectMapper.writeValueAsString?

更新:澄清一下,在给定MyObject 的情况下,我需要在我的URI(或URL 编码形式?object=%7B%22key%22%3A42%7D)中有?object={"key":42} 有一个属性key,其值等于42。

【问题讨论】:

  • 如果合适的话,您可以在MyObject.toString() 中使用ObjectMapper.writeValueAsString。
  • 我可以做到,但可能不会,原因有二。首先要让我的 DTO 独立于 Spring 上下文,因为我可能会在实际项目中通过上下文连接预配置的 ObjectMapper。第二,相当模糊的一个,我宁愿不引入将对象转换为 JSON 的替代路径,并在需要时直接调用 ObjectMapper 来保持明确。

标签: java json spring jackson resttemplate


【解决方案1】:

使用 writeValueAsString 有什么问题?你可以解释吗?

我想到的唯一解决方案是这样的(我不认为杰克逊是否有办法知道该对象应该在那一刻被序列化):

@Autowired
ObjectMapper objectMapper;

@Override
public void run(String... strings) throws Exception {

    String urlBase = "http://localhost:8080/path";

    RestTemplate restTemplate = new RestTemplate();

    String url;
    MultiValueMap<String, String> params = new LinkedMultiValueMap<String, String>();
    params.set("object", objectMapper.writeValueAsString(new MyObject()));

    UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(urlBase).queryParams(params);
    url = builder.build().toUri().toString();

    LOGGER.info("Composed before decode: " + url);

    //restTemplate.getForObject(url, Void.class);

    url = URLDecoder.decode(url, "UTF-8");

    LOGGER.info("Composed after decode: " + url);
}

输出:

2016-04-05 16:06:46.811  INFO 6728 --- [main] com.patrykwoj.StackOverfloApplication    : Composed before decode: http://localhost:8080/path?object=%7B%22key%22:43%7D
2016-04-05 16:06:46.941  INFO 6728 --- [main] com.patrykwoj.StackOverfloApplication    : Composed after decode: http://localhost:8080/path?object={"key":43}

编辑:

我忘了提一下,将 JSON 对象作为请求参数发送通常不是一个好主意。例如,您可能会遇到 JSON 中的大括号问题。

【讨论】:

  • 首先回答您编辑:是的,我同意将 JSON 用于查询参数并不是一个特别优雅的想法。可悲的是,这就是 Facebook 用于其某些端点的方式。
  • writeValueAsString 没有什么特别不好的。实际上,这就是我最终所做的。我想摆脱这种调用的原因与我们通常不手动将请求正文编写为 String 而是使用自动转换为 JSON 的对象的原因相同——方便。不必处理JsonProcessingException 也会让事情变得更简单。
  • 我不认为限制是问题所固有的。在编写请求正文时,Jackson 用来“知道”将什么序列化为 JSON 的相同逻辑可以应用于查询参数。没有实现它的最明显原因是不鼓励这种 API 设计风格(鉴于它在我们的控制之下),显然除了以往的历史原因。
猜你喜欢
  • 1970-01-01
  • 2017-09-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-03
  • 2017-09-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多