【发布时间】:2019-04-13 07:45:34
【问题描述】:
我正在尝试解析来自我无法控制的 Web 服务的 JSON 响应。
这些是标题
这是我在php中看到的隐藏敏感部分的主体
我正在使用 guzzle http 客户端发送请求并检索响应
如果我尝试直接解码它,我会收到一个空对象,所以我假设需要转换,所以我尝试像这样转换响应内容
json_decode(iconv($charset, 'UTF-8', $contents))
或
mb_convert_encoding($contents, 'UTF-8', $charset);
两者都抛出异常。
Notice: iconv(): Wrong charset, conversion from 'windows-1253' to 'UTF-8' is not allowed in Client.php on line 205
Warning: mb_convert_encoding(): Illegal character encoding specified in Client.php on line 208
我之前成功使用过这段代码,但我不明白为什么它现在失败了。
使用 POSTMAN 发送相同的请求可以正确检索没有损坏字符的数据,并且似乎显示接收到的相同标头和正文。
我正在根据 cmets 进行更新。
mb_detect_encoding($response->getBody()) -> UTF-8
mb_detect_encoding($response->getBody->getContents()) -> ASCII
json_last_error_msg -> UTF-8 格式错误,可能编码不正确
此外,作为一次试错尝试,我尝试了所有 iconv 编码,看看是否有任何可以将其转换为 utf-8 而不会出现错误以检测使用这个编码的编码
private function detectEncoding($str){
$iconvEncodings = [...]
$finalEncoding = "unknown";
foreach($iconvEncodings as $encoding){
try{
iconv($encoding, 'UTF-8', $str);
return $encoding;
}
catch (\Exception $exception){
continue;
}
}
return $finalEncoding;
}
显然没有编码工作,一切都给出了同样的例外。我假设问题在于通过 guzzle 正确检索响应 json 而不是 iconv 本身。它不可能不是1000多个中的任何一个。
有关 CURL 的更多信息
我刚刚使用 CURL 重试了相同的有效负载
/**
* @param $options
* @return bool|string
*/
public function makeCurlRequest($options)
{
$payload = json_encode($options);
// Prepare new cURL resource
$ch = curl_init($this->softoneurl);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true, // return web page
CURLOPT_HEADER => false, // don't return headers
CURLOPT_FOLLOWLOCATION => true, // follow redirects
CURLOPT_MAXREDIRS => 10, // stop after 10 redirects
CURLOPT_ENCODING => "", // handle compressed
CURLOPT_USERAGENT => "test", // name of client
CURLOPT_AUTOREFERER => true, // set referrer on redirect
CURLOPT_CONNECTTIMEOUT => 120, // time-out on connect
CURLOPT_TIMEOUT => 120, // time-out on response
CURLINFO_HEADER_OUT => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $payload,
]);
// Set HTTP Header for POST request
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json',
'Content-Length: ' . strlen($payload))
);
// Submit the POST request
$result = curl_exec($ch);
// Close cURL session handle
curl_close($ch);
return $result;
}
我收到了完全相同的字符串和转换后的完全相同的结果。也许我缺少一个选项?
显然,iconv 本身在环境中存在问题,它不是特定于应用程序的。通过 SSH 运行以下代码
php -r "var_dump(iconv('Windows-1253', 'UTF-8', 'test'));"
产量
PHP Notice: iconv(): Wrong charset, conversion from `Windows-1253' to `UTF-8' is not allowed in Command line code on line 1
PHP Stack trace:
PHP 1. {main}() Command line code:0
PHP 2. iconv(*uninitialized*, *uninitialized*, *uninitialized*) Command line code:1
Command line code:1:
bool(false)
可能缺少一些依赖
【问题讨论】:
-
json_last_error_msg()返回什么? -
另外,mb_detect_encoding 说的编码是什么?你知道它不是 UTF-8 吗?
-
我刚刚用我所看到的更新了我的问题。这很混乱。
-
Guzzle 没有正确读取结果。
-
mb_convert_encoding()不是 support Windows-1253 但iconv()应该可以正常工作。 JSON 必须编码为 UTF-8(它不是可选的),因此您需要在使用 JSON 函数之前对其进行修复。我建议你一次解决一件事。例如,将响应保存到文件,然后确定它是否真的使用 Windows-1253 以及iconv()是否可以修复它。