无法将 JSON 响应从 windows-1253 转换为 utf8
cannot convert JSON response from windows-1253 to utf8
我正在尝试解析来自我无法控制的 Web 服务的 JSON 响应。
这些是 headers
这是我在 php 中看到的 body 隐藏了敏感部分
我正在使用 guzzle http 客户端发送请求和检索响应
如果我尝试直接解码它,我会收到一个空 object 所以我假设需要转换,所以我尝试像这样转换响应内容
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 发送相同的请求可以正确地检索到没有损坏字符的数据,并且它似乎显示接收到相同的 headers 和 body。
我正在根据评论进行更新。
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)
可能缺少某些依赖项
试试这个:
$response = $guzzle->request('GET', $url);
$type = $response->getHeader('content-type');
$parsed = Psr7\parse_header($type);
$original_body = (string)$response->getBody();
$utf8_body = mb_convert_encoding($original_body, 'UTF-8', $parsed[0]['charset'] ?: 'UTF-8');
大约 14 个小时的故障排除后,我能够正确回答我自己的问题。在我的例子中,因为这是 运行ning 在 CLI 命令的上下文中,它导致了由于缺少库而导致的问题。基本上,CLI php 二进制文件无法访问某些 iconv 所需的库。
更具体地说是 gconv 库。
就我而言,在 Debian 9 中,它位于
/usr/lib/x86_64-linux-gnu/gconv
并且此文件夹包含大量用于每种编码的库。
理解这一点的一个好方法是,如果你 运行 在一个系统中你有根访问命令
strace iconv -f <needed_encoding> -t utf-8
它会产生许多 iconv 尝试访问的文件夹,包括 gconv 文件夹,并将指向您需要包含在 SSH 环境中的文件夹的位置。如果您没有 root 访问权限,则必须询问您的托管服务提供商。
我正在尝试解析来自我无法控制的 Web 服务的 JSON 响应。
这些是 headers
这是我在 php 中看到的 body 隐藏了敏感部分
我正在使用 guzzle http 客户端发送请求和检索响应
如果我尝试直接解码它,我会收到一个空 object 所以我假设需要转换,所以我尝试像这样转换响应内容
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 发送相同的请求可以正确地检索到没有损坏字符的数据,并且它似乎显示接收到相同的 headers 和 body。
我正在根据评论进行更新。
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)
可能缺少某些依赖项
试试这个:
$response = $guzzle->request('GET', $url);
$type = $response->getHeader('content-type');
$parsed = Psr7\parse_header($type);
$original_body = (string)$response->getBody();
$utf8_body = mb_convert_encoding($original_body, 'UTF-8', $parsed[0]['charset'] ?: 'UTF-8');
大约 14 个小时的故障排除后,我能够正确回答我自己的问题。在我的例子中,因为这是 运行ning 在 CLI 命令的上下文中,它导致了由于缺少库而导致的问题。基本上,CLI php 二进制文件无法访问某些 iconv 所需的库。
更具体地说是 gconv 库。 就我而言,在 Debian 9 中,它位于
/usr/lib/x86_64-linux-gnu/gconv
并且此文件夹包含大量用于每种编码的库。 理解这一点的一个好方法是,如果你 运行 在一个系统中你有根访问命令
strace iconv -f <needed_encoding> -t utf-8
它会产生许多 iconv 尝试访问的文件夹,包括 gconv 文件夹,并将指向您需要包含在 SSH 环境中的文件夹的位置。如果您没有 root 访问权限,则必须询问您的托管服务提供商。