JSON无效的UTF-8中间字节

51

当(在这种情况下是Jackson JSON引擎)尝试解析一些未使用UTF-8编码的JSON时,会出现此错误。

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

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);

错误日志:

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)
7个回答

43

当我在Java客户端应用程序中序列化JSON时,出现了这个异常

String json = mapper.writeValueAsString(contentBean);

在服务器端,我使用Spring Boot作为REST终端点。异常信息如下:

嵌套异常是com.fasterxml.jackson.databind.JsonMappingException: Invalid UTF-8 start byte 0xaa。

我的问题是,我没有在HTTP客户端上设置正确的编码方式。以下操作解决了我的问题:

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

Android设置HttpPost的内容类型


对我来说,只需要在StringEntity上设置字符集为UTF-8就足够了。 - avg
2
这对我有用,我使用了 MediaType.APPLICATION_JSON_UTF8_VALUE 而不是手动编写字符串。 - Dot Batch
@DotBatch 谢谢你提供的简单而优雅的解决方案。 :) - Dark Star1
1
谢谢,将 ;charset=UTF-8 添加到请求头中有所帮助。 - Dmitriy Popov
对于在JIRA中遇到此错误的任何人,这个解决方案,即添加; charset = UTF-8,为我解决了问题。 - user2728841

38

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

       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等)对数据进行编码。


2
顺便说一句,这正是Jackson所做的——挑战只在于ISO-8859-x在这个意义上看起来像UTF-8。但由于非Unicode编码不允许与Unicode一起使用,因此对于有效的JSON来说,这不是一个问题。 - StaxMan
3
在我的情况下,是因为在创建文件时,我对FileObjectStream#write()使用了content.toString()。getBytes()(其中contentJsonNode),导致问题发生 - 看起来相同,但实际上不同!修复方法是使用new ObjectMapper()。writeValueAsBytes(content)。意识到这一点后,我将其作为评论添加在这里,以防其他人遇到同样的问题,并且它对他们有所帮助。 - SteveR

5

我使用Notepad2保存JSON文件之后得到了这个问题,所以我必须使用Notepad++打开它,然后选择“转换为UTF-8”。之后它就正常工作了。


3

万一有所帮助,我想分享一个相关轶事。

我在使用PowerShell集成脚本环境(ISE)运行PowerShell脚本时遇到了这个错误(Invalid UTF-8 middle byte 0x3f)。在ISE之外执行相同的脚本是没有问题的。该代码使用Confluence v3和v5.x REST API,这个错误被记录在Confluence v5.x服务器上,可能是因为ISE某种方式干扰了请求。


2
这个答案 解决了我的问题。以下是它的复制:

确保使用 -Dfile.encoding=UTF-8 启动JVM。你的JVM默认使用操作系统字符集

这是一个JVM参数,可以被添加到JBoss独立或从Eclipse运行的JBoss中。

在我这里,这个问题只在我们团队中的一台电脑上发生。其他人都没有这个问题。


1
我曾在不同平台上遇到这个问题,因为我从Mapper中获取JSON字符串并自己进行编写。有时它以ansi格式进入文件,而其他时候则正确地以UTF8格式进入。我转换为UTF8后问题得到解决。
mapper.writeValue(file, data);

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

0

客户端文本协议

POST http://127.0.0.1/bom/create HTTP/1.1
Content-Type: application/json
User-Agent: PostmanRuntime/7.25.0
Accept: */*
Postman-Token: 50ecfbfe-741f-4a2b-a3d3-cdf162ada27f
Host: 127.0.0.1
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Content-Length: 405

{
  "fwoid": 1,
  "list": [
    {
      "bomIndex": "10001",
      "desc": "带GH 1.25 13pin 公座带针 白色",
      "pn": "084.0001.0036",
      "preUse": 1,
      "type": "追觅 除螨仪-开关PCB组件"
    },
     {
      "bomIndex": "10002",
      "desc": "紫米音箱-商品码标签",
      "pn": "Z.08.013.0051",
      "preUse": 1,
      "type": "E060A0302301"
    }
  ]
}
HTTP/1.1 200 OK
Connection: keep-alive
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Content-Type: application/json
Date: Mon, 01 Jun 2020 11:23:42 GMT
Content-Length: 40

{"code":"0","message":"BOM保存成功"}

以下是一个SpringBoot控制器的代码:

@PostMapping("/bom/create")
@ApiOperation(value = "保存BOM")
@BusinessOperation(module = "BOM",methods = "解析BOM")
public JsonResult save(@RequestBody BOMSaveQuery query)
{
    return bomService.saveBomList(query);
}

当我在回环接口上调试时,它正常工作。但是通过批处理命令部署到互联网服务器时,我遇到了一个错误

ServletInvocableHandlerMethod - Could not resolve parameter [0] in public XXXController.save(com.h2.mes.query.BOMSaveQuery): JSON parse error: Invalid UTF-8 middle byte 0x3f; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Invalid UTF-8 middle byte 0x3f
 at [Source: (PushbackInputStream); line: 9, column: 32] (through reference chain: com.h2.mes.query.BOMSaveQuery["list"]->java.util.ArrayList[0]->com.h2.mes.vo.BOMVO["type"])
2020-06-01 15:37:50.251 MES [XNIO-1 task-13] WARN  o.s.w.s.m.s.DefaultHandlerExceptionResolver - Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Invalid UTF-8 middle byte 0x3f; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Invalid UTF-8 middle byte 0x3f
 at [Source: (PushbackInputStream); line: 9, column: 32] (through reference chain: com.h2.mes.query.BOMSaveQuery["list"]->java.util.ArrayList[0]->com.h2.mes.vo.BOMVO["type"])]
2020-06-01 15:37:50.251 MES [XNIO-1 task-13] DEBUG o.s.web.servlet.DispatcherServlet - Completed 400 BAD_REQUEST
2020-06-01 15:37:50.251 MES [XNIO-1 task-13] DEBUG o.s.web.servlet.DispatcherServlet - "ERROR" dispatch for POST "/error", parameters={}

为我起作用的是添加JVM参数。 java -Dfile.encoding=UTF-8


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接