无法在URL中记录JSON

时间:2015-10-01 10:42:32

标签: java json spring spring-restdocs

在我的Rest API中,应该可以检索边界框内的数据。因为边界框有四个坐标,我想以这种方式设计GET请求,它们接受边界框作为JSON。因此,我需要能够将JSON字符串作为URL参数发送和记录。

测试本身有效,但我无法使用Spring RestDocs(1.0.0.RC1)记录这些请求。我用一种更简单的方法重现了这个问题。见下文:

  @Test public void ping_username() throws Exception
  {
    String query = "name={\"user\":\"Müller\"}";
    String encodedQuery = URLEncoder.encode(query, "UTF-8");
    mockMvc.perform(get(URI.create("/ping?" + encodedQuery)))
            .andExpect(status().isOk())
            .andDo(document("ping_username"));
  }

当我删除.andDo(document("ping_username"))测试通过时。

堆栈跟踪:

java.lang.IllegalArgumentException: Illegal character in query at index 32: http://localhost:8080/ping?name={"user":"Müller"}
    at java.net.URI.create(URI.java:852)
    at org.springframework.restdocs.mockmvc.MockMvcOperationRequestFactory.createOperationRequest(MockMvcOperationRequestFactory.java:79)
    at org.springframework.restdocs.mockmvc.RestDocumentationResultHandler.handle(RestDocumentationResultHandler.java:93)
    at org.springframework.test.web.servlet.MockMvc$1.andDo(MockMvc.java:158)
    at application.rest.RestApiTest.ping_username(RestApiTest.java:65)

在我收到编码URL的建议后,我尝试了,但问题仍然存在。

用于在我的测试中创建URI的String现在是/ping?name%3D%7B%22user%22%3A%22M%C3%BCller%22%7D

我检查了堆栈跟踪中出现的类MockMvcOperationRequestFactory,然后在第79行执行以下代码:

URI.create(getRequestUri(mockRequest)
                + (StringUtils.hasText(queryString) ? "?" + queryString : ""))

这里的问题是使用了未编码的字符串(在我的情况下为http://localhost:8080/ping?name={"user":"Müller"}),并且URI的创建失败。

注:

Andy Wilkinson的答案是解决问题的方法。虽然我认为David Sinfield是正确的,但URL中应避免使用JSON来保持简单。对于我的边界框,我将使用逗号分隔的字符串,因为它在WMS 1.1中使用:BBOX=x1,y1,x2,y2

2 个答案:

答案 0 :(得分:1)

问题是URI必须编码为ACII。并且ü不是有效的ASCII字符,因此必须在%转义的网址中对其进行转义。

如果您使用的是Tomcat,则可以在URIEncoding="UTF-8"的{​​{1}}元素中使用Connector,将UTF-8转义配置为默认值。如果这样做,server.xml将自动转换为ü,这是%C3%BC Unicode代码点(代表\uC3BC)的ASCII表示。

编辑:似乎我错过了错误的确切位置,但仍然是同样的错误。 URI中的大括号无效。根据RFC 3986,只接受以下字符:

ü

所以这些也必须被转义。

答案 1 :(得分:1)

您还没有提到您正在使用的Spring REST文档的版本,但我猜测问题出在URIUtil上。我无法确定,因为我无法看到URIUtil的来源。

无论如何,使用JDK' URLEncoder可以使用Spring REST Docs 1.0.0.RC1:

String query = "name={\"user\":\"Müller\"}";
String encodedQuery = URLEncoder.encode(query, "UTF-8");
mockMvc.perform(get(URI.create("/baz?" + encodedQuery)))
        .andExpect(status().isOk())
        .andDo(document("ping_username"));

然后,您可以在服务器端使用URLDecoder.decode来获取原始JSON:

URLDecoder.decode(request.getQueryString(), "UTF-8")