java 解析 JSON 时出现杰克逊错误“非法字符......只允许使用常规空格”
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/42621547/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Hymanson error "Illegal character... only regular white space allowed" when parsing JSON
提问by rogger2016
I am trying to retrieve JSON data from a URL but get the following error:
我正在尝试从 URL 检索 JSON 数据,但出现以下错误:
Illegal character ((CTRL-CHAR, code 31)):
only regular white space (\r, \n,\t) is allowed between tokens
My code:
我的代码:
final URI uri = new URIBuilder(UrlConstants.SEARCH_URL)
.addParameter("keywords", searchTerm)
.addParameter("count", "50")
.build();
node = new ObjectMapper().readTree(new URL(uri.toString())); <<<<< THROWS THE ERROR
The url constructed is i.e https://www.example.org/api/search.json?keywords=iphone&count=50
构造的url为即https://www.example.org/api/search.json?keywords=iphone&count=50
What is going wrong here? And how can I parse this data successfully?
这里出了什么问题?我怎样才能成功解析这些数据?
Imports:
进口:
import com.google.appengine.repackaged.org.codehaus.Hymanson.JsonNode;
import com.google.appengine.repackaged.org.codehaus.Hymanson.map.ObjectMapper;
import com.google.appengine.repackaged.org.codehaus.Hymanson.node.ArrayNode;
import org.apache.http.client.utils.URIBuilder;
example response
示例响应
{
meta: {
indexAllowed: false
},
products: {
products: [
{
id: 1,
name: "Apple iPhone 6 16GB 4G LTE GSM Factory Unlocked"
},
{
id: 2,
name: "Apple iPhone 7 8GB 4G LTE GSM Factory Unlocked"
}
]
}
}
采纳答案by sleske
The message should be pretty self-explanatory:
该消息应该是不言自明的:
There is an illegal character (in this case character code 31, i.e. the control code "Unit Separator") in the JSON you are processing.
您正在处理的 JSON 中存在非法字符(在本例中为字符代码 31,即控制代码“Unit Separator”)。
In other words, the data you are receiving is not proper JSON.
换句话说,您收到的数据不是正确的 JSON。
Background:
背景:
The JSON spec (RFC 7159) says:
JSON 规范 ( RFC 7159) 说:
- JSON Grammar
A JSON text is a sequence of tokens. The set of tokens includes six tructural characters, strings, numbers, and three literal names.
[...]
Insignificant whitespace is allowed before or after any of the six structural characters.
ws = *(
%x20 / ; Space
%x09 / ; Horizontal tab
%x0A / ; Line feed or New line
%x0D ) ; Carriage return
- JSON 语法
JSON 文本是一个令牌序列。令牌集包括六个结构字符、字符串、数字和三个文字名称。
[...]
在六个结构字符中的任何一个之前或之后都允许使用无关紧要的空格。
ws = *(
%x20 / ; 空间
%x09 / ; 水平标签
%x0A / ; 换行或换行
%x0D); 回车
In other words: JSON may contain whitespace between the tokens ("tokens" meaning the part of the JSON, i.e. lists, strings etc.), but "whitespace" is defined to only mean the characters Space, Tab, Line feed and Carriage return.
换句话说:JSON 可能包含令牌之间的空格(“令牌”表示 JSON 的一部分,即列表、字符串等),但“空格”被定义为仅表示字符 Space、Tab、换行和回车.
Your document contains something else (code 31) where only whitespace is allowed, hence is not valid JSON.
您的文档包含其他内容(代码 31),其中只允许使用空格,因此不是有效的 JSON。
To parse this:
要解析这个:
Unfortunately, the Hymanson library you are using does not offer a way to parse this malformed data. To parse this successfully, you will have to filter the JSON before it is handled by Hymanson.
不幸的是,您使用的 Hymanson 库没有提供解析这种格式错误的数据的方法。要成功解析它,您必须在 Hymanson 处理 JSON 之前对其进行过滤。
You will probably have to retrieve the (pseudo-)JSON yourself from the REST service, using standard HTTP using, e.g. java.net.HttpUrlConnection. Then suitably filter out "bad" characters, and pass the resulting string to Hymanson. How to do this exactly depends on how you use Hymanson.
您可能必须自己从 REST 服务中检索(伪)JSON,使用标准 HTTP,例如java.net.HttpUrlConnection。然后适当地过滤掉“坏”字符,并将结果字符串传递给Hyman逊。如何做到这一点完全取决于您如何使用 Hymanson。
Feel free to ask a separate questions if you are having trouble :-).
如果您遇到问题,请随时提出单独的问题:-)。
回答by ChocolateAndCheese
I got this same issue, and I found that it was caused by the Content-Encoding: gzip
header. The client application (where the exception was being thrown) was not able to handle this content-encoding. FWIW the client application was using io.github.openfeign:feign-core:9.5.0
, and this library appears to have some issues around compression (link).
我遇到了同样的问题,我发现它是由Content-Encoding: gzip
标题引起的。客户端应用程序(抛出异常的地方)无法处理此内容编码。FWIW 客户端应用程序正在使用io.github.openfeign:feign-core:9.5.0
,并且该库似乎在压缩(链接)方面存在一些问题。
You might try adding the header Accept-Encoding: identity
to your request, however, not all web servers/web applications are configured properly, and some seem to disregard this header. See this questionfor more details about how to prevent gzipped content.
您可以尝试将标头添加Accept-Encoding: identity
到您的请求中,但是,并非所有 Web 服务器/Web 应用程序都配置正确,有些似乎忽略了此标头。有关如何防止压缩内容的更多详细信息,请参阅此问题。
回答by Yash
I had a similar issue. After some research, I found of that restTemplate uses the SimpleClientHttpRequestFactory which does not support gzip encoding. To enable gzip encoding for your response, you will need to set a new request factory for the rest template object - HttpComponentsClientHttpRequestFactory.
我有一个类似的问题。经过一番研究,我发现 restTemplate 使用了不支持 gzip 编码的 SimpleClientHttpRequestFactory 。要为您的响应启用 gzip 编码,您需要为其余模板对象 - HttpComponentsClientHttpRequestFactory 设置一个新的请求工厂。
restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory());
restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory());
回答by Gayan Chinthaka
I had the same problem. After setting Gzip it was fixed. Please refer my code
我有同样的问题。设置 Gzip 后就修复了。请参考我的代码
public String sendPostRequest(String req) throws Exception {
// Create connection
URL urlObject = new URL(mURL);
HttpURLConnection connection = (HttpURLConnection) urlObject.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/json");
connection.setRequestProperty("Content-Length", Integer.toString(req.getBytes().length));
connection.setRequestProperty("Content-Language", "en-US");
connection.setUseCaches(false);
connection.setDoOutput(true);
// Send request
DataOutputStream wr = new DataOutputStream(connection.getOutputStream());
wr.writeBytes(req);
wr.close();
//Response handling
InputStream responseBody = null;
if (isGzipResponse(connection)) {
responseBody = new GZIPInputStream(connection.getInputStream());
}else{
responseBody = connection.getInputStream();
}
convertStreamToString(responseBody);
return response.toString();
}
protected boolean isGzipResponse(HttpURLConnection con) {
String encodingHeader = con.getHeaderField("Content-Encoding");
return (encodingHeader != null && encodingHeader.toLowerCase().indexOf("gzip") != -1);
}
public void convertStreamToString(InputStream in) throws Exception {
if (in != null) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[4096];
int length = 0;
while ((length = in.read(buffer)) != -1) {
baos.write(buffer, 0, length);
}
response = new String(baos.toByteArray());
baos.close();
} else {
response = null;
}
}