无法将JSON响应从Windows-1253转换为utf8

时间:2019-04-12 13:02:49

标签: php .net json guzzle

我正试图从无法控制的Web服务解析JSON响应。

这些是标题

enter image description here

这是我在php中看到的身体,其中隐藏了敏感部分

enter image description here

我正在使用耗时的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发送相同的请求可以正确检索数据,而不会损坏字符,并且似乎显示出相同的标题和正文。

我正在根据评论进行更新。

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

显然,没有编码有效,并且所有内容都给出了相同的异常。我假设问题在于通过食口而不是iconv本身正确检索响应json。不可能不是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)

也许缺少某些依赖项

2 个答案:

答案 0 :(得分:1)

大约14小时后进行故障排除,我能够正确回答自己的问题。就我而言,由于它是在CLI命令的上下文中运行的,因此由于缺少库而导致了问题。基本上,CLI php二进制文件无法访问所需的某些库iconv。

更具体地说,是gconv库。 在我的Debian 9中,它位于

/usr/lib/x86_64-linux-gnu/gconv

,此文件夹包含许多用于每种编码的库。 理解这一点的一种好方法是,如果您在系统中运行,则具有root访问命令

strace iconv -f <needed_encoding> -t utf-8

这将产生iconv尝试访问的许多文件夹,包括gconv文件夹,并将您指向需要包含在SSH环境中的文件夹的位置。如果您没有超级用户访问权限,则必须询问托管服务提供商。

答案 1 :(得分:0)

尝试一下:

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