HttpMessageNotReadableException: JSON parse error: Unrecognized token '嬀崀'
HttpMessageNotReadableException: JSON parse error: Unrecognized token '嬀崀'
我正在通过 RestTemplate 调用端点,如下所示:
SSLContext sslContext = SSLContexts.createSystemDefault();
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslContext);
HttpClient client = HttpClientBuilder.create().setSSLSocketFactory(socketFactory).build();
ClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(client);
HttpEntity<String> entity = new HttpEntity<>(requestJson, headers());
Object[] response = restTemplate.postForObject(uri, entity, Object[].class);
我已经验证 entity
object 中的 JSON 字符串是有效的,方法是复制它并在对同一端点的 cURL 请求中使用它,没有任何错误。此请求中也使用了相同的 headers 和授权令牌。
当我执行 POST 时,我返回以下错误:
Error while extracting response for type [class [Ljava.lang.Object;] and content type [application/json;charset=utf-16]
org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Unrecognized token '嬀崀': was expecting (JSON String, Number, Array, Object or token 'null', 'true' or 'false'); nested exception is com.fasterxml.jackson.core.JsonParseException: Unrecognized token '嬀崀': was expecting (JSON String, Number, Array, Object or token 'null', 'true' or 'false')
at [Source: (InputStreamReader); line: 1, column: 3]
我的accept
和content-type
headers都设置为application/json
。通过检查 cURL 的输出,我发现响应中没有中文字符 body.
回复headers如下:
Connection →keep-alive
Content-Encoding →gzip
Content-Type →application/json; charset=utf-8
Date → xxx
Transfer-Encoding →chunked
Vary →Accept-Encoding
当我请求responseType
设置为String.class
或Object.class
时,响应是汉字:
restTemplate.postForObject(uri, entity, String.class);
嬀崀
我希望这个调用 return 一个空数组 []
。
当我将 requestJson
字符串更改为应该返回 non-empty 数组的字符串时,我得到了数百个汉字,而不是两个。
我如何像使用 cURL 一样解码响应以获得有效数据?
编辑:
我不确定这有什么关系,但是空数组[]
中字符的字节码是91和93,这两个汉字的字节码是0、91、0, 93.
restTemplate 的响应似乎是一个汉字字符串而不是一个数组。您发布的第一个错误似乎表明问题出在将响应提取到 Object[]
中。如果来自 restTemplate 的响应实际上是一个字符串,那么这也可以解释第二个错误。 RestTemplate 期望解析一个数组,但却收到了字符串 嬀崀
。这就是将响应类型更改为 String.class
似乎有效的原因。
如果您希望从您呼叫的 api 返回一个 JSON 数组,那么我会仔细检查您呼叫的 api 的响应。否则,我建议改用 String.class
。
已编辑:
有可能 restTemplate 正在使用 utf-16
字符集解析响应,而服务器正在使用 utf-8
字符集对响应进行编码。就像您在描述中发布的那样,这些字符似乎具有相同的字节码。也许将 restTemplate 中的预期字符集更改为 utf-8
将解决您的问题。
不要使用UTF16。 HTTP 规范说 ASCII,许多使用 UTF8。该错误用 charset=utf-16
指出了这一点。尝试根据请求设置编码 header。
正如您在字符代码中指出的那样,您所看到的正是使用 UTF16 时预期的结果,因为每个字符都是 2 个字节。
当我从 cURL 调用它时,API 返回 UTF-8 内容,但是当我以编程方式调用 API 时,尽管我提出请求,它仍然返回 UTF-16LE headers 明确要求 UTF-8。
我需要做一些 de-/en-coding 游戏,但以下内容让我能够观察到有效的预期响应 JSON:
ResponseEntity<byte[]> responseEntity = restTemplate.postForEntity(uri, entity, byte[].class);
byte[] bytes = responseEntity.getBody();
String json = new String(bytes, StandardCharsets.UTF_16LE);
FooBar[] fooBar = objectMapper.readValue(json, FooBar[].class);
我正在通过 RestTemplate 调用端点,如下所示:
SSLContext sslContext = SSLContexts.createSystemDefault();
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslContext);
HttpClient client = HttpClientBuilder.create().setSSLSocketFactory(socketFactory).build();
ClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(client);
HttpEntity<String> entity = new HttpEntity<>(requestJson, headers());
Object[] response = restTemplate.postForObject(uri, entity, Object[].class);
我已经验证 entity
object 中的 JSON 字符串是有效的,方法是复制它并在对同一端点的 cURL 请求中使用它,没有任何错误。此请求中也使用了相同的 headers 和授权令牌。
当我执行 POST 时,我返回以下错误:
Error while extracting response for type [class [Ljava.lang.Object;] and content type [application/json;charset=utf-16]
org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Unrecognized token '嬀崀': was expecting (JSON String, Number, Array, Object or token 'null', 'true' or 'false'); nested exception is com.fasterxml.jackson.core.JsonParseException: Unrecognized token '嬀崀': was expecting (JSON String, Number, Array, Object or token 'null', 'true' or 'false')
at [Source: (InputStreamReader); line: 1, column: 3]
我的accept
和content-type
headers都设置为application/json
。通过检查 cURL 的输出,我发现响应中没有中文字符 body.
回复headers如下:
Connection →keep-alive
Content-Encoding →gzip
Content-Type →application/json; charset=utf-8
Date → xxx
Transfer-Encoding →chunked
Vary →Accept-Encoding
当我请求responseType
设置为String.class
或Object.class
时,响应是汉字:
restTemplate.postForObject(uri, entity, String.class);
嬀崀
我希望这个调用 return 一个空数组 []
。
当我将 requestJson
字符串更改为应该返回 non-empty 数组的字符串时,我得到了数百个汉字,而不是两个。
我如何像使用 cURL 一样解码响应以获得有效数据?
编辑:
我不确定这有什么关系,但是空数组[]
中字符的字节码是91和93,这两个汉字的字节码是0、91、0, 93.
restTemplate 的响应似乎是一个汉字字符串而不是一个数组。您发布的第一个错误似乎表明问题出在将响应提取到 Object[]
中。如果来自 restTemplate 的响应实际上是一个字符串,那么这也可以解释第二个错误。 RestTemplate 期望解析一个数组,但却收到了字符串 嬀崀
。这就是将响应类型更改为 String.class
似乎有效的原因。
如果您希望从您呼叫的 api 返回一个 JSON 数组,那么我会仔细检查您呼叫的 api 的响应。否则,我建议改用 String.class
。
已编辑:
有可能 restTemplate 正在使用 utf-16
字符集解析响应,而服务器正在使用 utf-8
字符集对响应进行编码。就像您在描述中发布的那样,这些字符似乎具有相同的字节码。也许将 restTemplate 中的预期字符集更改为 utf-8
将解决您的问题。
不要使用UTF16。 HTTP 规范说 ASCII,许多使用 UTF8。该错误用 charset=utf-16
指出了这一点。尝试根据请求设置编码 header。
正如您在字符代码中指出的那样,您所看到的正是使用 UTF16 时预期的结果,因为每个字符都是 2 个字节。
当我从 cURL 调用它时,API 返回 UTF-8 内容,但是当我以编程方式调用 API 时,尽管我提出请求,它仍然返回 UTF-16LE headers 明确要求 UTF-8。
我需要做一些 de-/en-coding 游戏,但以下内容让我能够观察到有效的预期响应 JSON:
ResponseEntity<byte[]> responseEntity = restTemplate.postForEntity(uri, entity, byte[].class);
byte[] bytes = responseEntity.getBody();
String json = new String(bytes, StandardCharsets.UTF_16LE);
FooBar[] fooBar = objectMapper.readValue(json, FooBar[].class);