关于jackson:JSON无效的UTF-8中间字节

JSON Invalid UTF-8 middle byte

当(杰克逊,在这种情况下)JSON引擎尝试解析一些未使用UTF-8编码的JSON时,会发生此错误。

如何告诉引擎它应该期望与UTF-8不同的东西,例如UTF-16?

1
2
3
4
5
HttpHeaders requestHeaders = createSomeHeader();
RestTemplate restTemplate = new RestTemplate();
HttpEntity< ? > requestEntity = new HttpEntity<Object>(requestHeaders);
String url ="someurl"
ResponseEntity<MyObject[]> arrayResponseEntity = restTemplate.exchange(url, HttpMethod.GET, requestEntity, MyObject[].class);

错误日志:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Caused by: org.springframework.http.converter.HttpMessageNotReadableException: Could not read JSON: Invalid UTF-8 middle byte 0x20
at [Source: org.apache.http.conn.EofSensorInputStream@44d397b0; line: 92, column: 42]; nested exception is org.codehaus.jackson.JsonParseException: Invalid UTF-8 middle byte 0x20
at [Source: org.apache.http.conn.EofSensorInputStream@44d397b0; line: 92, column: 42]
at org.springframework.http.converter.json.MappingJacksonHttpMessageConverter.readInternal(MappingJacksonHttpMessageConverter.java:138)
at org.springframework.http.converter.AbstractHttpMessageConverter.read(AbstractHttpMessageConverter.java:154)
at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:74)
at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:622)
at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:608)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:449)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:404)
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:380)
... 4 more
Caused by: org.codehaus.jackson.JsonParseException: Invalid UTF-8 middle byte 0x20
at [Source: org.apache.http.conn.EofSensorInputStream@44d397b0; line: 92, column: 42]
at org.codehaus.jackson.JsonParser._constructError(JsonParser.java:1213)
at org.codehaus.jackson.impl.JsonParserMinimalBase._reportError(JsonParserMinimalBase.java:375)
at org.codehaus.jackson.impl.Utf8StreamParser._reportInvalidOther(Utf8StreamParser.java:2132)
at org.codehaus.jackson.impl.Utf8StreamParser._reportInvalidOther(Utf8StreamParser.java:2139)
at org.codehaus.jackson.impl.Utf8StreamParser._decodeUtf8_3fast(Utf8StreamParser.java:1962)

JSON数据必须编码为UTF-8,UTF-16或UTF-32。 JSON解码器可以通过检查字节流的前四个八位字节来确定编码:

1
2
3
4
5
       00 00 00 xx  UTF-32BE
       00 xx 00 xx  UTF-16BE
       xx 00 00 00  UTF-32LE
       xx 00 xx 00  UTF-16LE
       xx xx xx xx  UTF-8

听起来好像服务器正在以某种非法编码(ISO-8859-1,Windows-1252等)编码数据。


在Java客户端应用程序中像这样序列化JSON时遇到了此异常

1
String json = mapper.writeValueAsString(contentBean);

在服务器端,我使用Spring Boot作为REST端点。
例外是:

嵌套的异常是com.fasterxml.jackson.databind.JsonMappingException:无效的UTF-8起始字节0xaa

我的问题是,我没有在HTTP客户端上设置正确的编码。
这解决了我的问题:

1
2
3
updateRequest.setHeader("Content-Type","application/json;charset=UTF-8");
StringEntity entity= new StringEntity(json,"UTF-8");
updateRequest.setEntity(entity);

Android设置内容类型HttpPost


我在使用Notepad2保存JSON文件后得到了此信息,因此我不得不使用Notepad ++打开它,然后说"转换为UTF-8"。然后它起作用了。


如果有机会,我可能会与他人分享相关的轶事。

我在通过PowerShell集成脚本环境(ISE)运行PowerShell脚本时遇到此确切错误(无效的UTF-8中间字节0x3f)。在ISE外部执行的相同脚本可以正常工作。该代码使用Confluence v3和v5.x REST API,并且此错误记录在Confluence v5.x服务器上-大概是因为ISE莫名其妙地拒绝了该请求。


我在不同平台之间不一致地遇到了这个问题,因为我是从Mapper获得JSON作为String并自己编写的。有时,它以ansi形式进入文件,而其他时候则以UTF8形式正确进入。我切换到

1
mapper.writeValue(file, data);

让Mapper进行文件操作,它开始工作正常。