47

我遇到了一个非常奇怪的问题。

我有一个 JSON 网络服务。

当我用这个网站检查它时http://www.freeformatter.com/json-formatter.html#ad-output

一切都好。

但是当我用这段代码加载我的 JSON 时:

  $data = file_get_contents('http://www.mywebservice');

if(!empty($data))
{

    $obj = json_decode($data);

 switch (json_last_error()) {
    case JSON_ERROR_NONE:
        echo ' - JSON_ERROR_NONE';
    break;
    case JSON_ERROR_DEPTH:
        echo ' - JSON_ERROR_DEPTH';
    break;
    case JSON_ERROR_STATE_MISMATCH:
        echo ' - JSON_ERROR_STATE_MISMATCH';
    break;
    case JSON_ERROR_CTRL_CHAR:
        echo ' -  JSON_ERROR_CTRL_CHAR';
    break;
    case JSON_ERROR_SYNTAX:
        echo "\r\n\r\n - SYNTAX ERROR \r\n\r\n";
    break;
    case JSON_ERROR_UTF8:
        echo ' - JSON_ERROR_UTF8';
    break;
    default:
        echo ' - Unknown erro';
    break;
}

我得到了错误:语法错误

这根本没有帮助。

这是一场噩梦。

我看到使用 PHP 5.5 我可以使用这个函数: http: //php.net/manual/en/function.json-last-error-msg.php

(但我还没有成功安装 PHP 5.5,我不确定这个函数会给我更多细节)

4

17 回答 17

91

我遇到了同样的问题,实际上有一些隐藏的字符看不见,你需要删除它。这是适用于许多情况的全局代码:

<?php
$checkLogin = file_get_contents("http://yourwebsite.com/JsonData");

// This will remove unwanted characters.
// Check http://www.php.net/chr for details
for ($i = 0; $i <= 31; ++$i) { 
    $checkLogin = str_replace(chr($i), "", $checkLogin); 
}
$checkLogin = str_replace(chr(127), "", $checkLogin);

// This is the most common part
// Some file begins with 'efbbbf' to mark the beginning of the file. (binary level)
// here we detect it and we remove it, basically it's the first 3 characters 
if (0 === strpos(bin2hex($checkLogin), 'efbbbf')) {
   $checkLogin = substr($checkLogin, 3);
}

$checkLogin = json_decode( $checkLogin );
print_r($checkLogin);
?>
于 2013-12-30T18:55:20.483 回答
60

删除BOM(字节顺序标记)通常是您需要的解决方案:

function removeBOM($data) {
    if (0 === strpos(bin2hex($data), 'efbbbf')) {
       return substr($data, 3);
    }
    return $data;
}

你不应该有 BOM,但如果它在那里,它是不可见的,所以你不会看到它!

参见W3C 关于 BOM 的 HTML

如果您有很多文件要修复,请使用BOM Cleaner 。

于 2015-07-23T18:07:20.680 回答
34

我解决了这个问题,在 json_decode 之前向字符串添加斜杠。

$data = stripslashes($data); 
$obj = json_decode($data);
于 2015-02-16T11:46:58.350 回答
7

为了将所有东西放在一起,我准备了带有解码自动纠正操作的 JSON 包装器。最新版本可以在我的GitHub Gist中找到。

abstract class Json
{
    public static function getLastError($asString = FALSE)
    {
        $lastError = \json_last_error();

        if (!$asString) return $lastError;

        // Define the errors.
        $constants = \get_defined_constants(TRUE);
        $errorStrings = array();

        foreach ($constants["json"] as $name => $value)
            if (!strncmp($name, "JSON_ERROR_", 11))
                $errorStrings[$value] = $name;

        return isset($errorStrings[$lastError]) ? $errorStrings[$lastError] : FALSE;
    }

    public static function getLastErrorMessage()
    {
        return \json_last_error_msg();
    }

    public static function clean($jsonString)
    {
        if (!is_string($jsonString) || !$jsonString) return '';

        // Remove unsupported characters
        // Check http://www.php.net/chr for details
        for ($i = 0; $i <= 31; ++$i)
            $jsonString = str_replace(chr($i), "", $jsonString);

        $jsonString = str_replace(chr(127), "", $jsonString);

        // Remove the BOM (Byte Order Mark)
        // It's the most common that some file begins with 'efbbbf' to mark the beginning of the file. (binary level)
        // Here we detect it and we remove it, basically it's the first 3 characters.
        if (0 === strpos(bin2hex($jsonString), 'efbbbf')) $jsonString = substr($jsonString, 3);

        return $jsonString;
    }

    public static function encode($value, $options = 0, $depth = 512)
    {
        return \json_encode($value, $options, $depth);
    }

    public static function decode($jsonString, $asArray = TRUE, $depth = 512, $options = JSON_BIGINT_AS_STRING)
    {
        if (!is_string($jsonString) || !$jsonString) return NULL;

        $result = \json_decode($jsonString, $asArray, $depth, $options);

        if ($result === NULL)
            switch (self::getLastError())
            {
                case JSON_ERROR_SYNTAX :
                    // Try to clean json string if syntax error occured
                    $jsonString = self::clean($jsonString);
                    $result = \json_decode($jsonString, $asArray, $depth, $options);
                    break;

                default:
                    // Unsupported error
            }

        return $result;
    }
}

示例用法:

$json_data = file_get_contents("test.json");
$array = Json::decode($json_data, TRUE);
var_dump($array);
echo "Last error (" , Json::getLastError() , "): ", Json::getLastError(TRUE), PHP_EOL;
于 2017-04-29T10:10:48.630 回答
5

在我的情况下:

json_decode(html_entity_decode($json_string));

于 2020-06-19T21:36:01.463 回答
3

我有同样的问题,接收JSON_ERROR_CTRL_CHARJSON_ERROR_SYNTAX
这是我的修复。

$content = json_decode(json_encode($content), true);
于 2019-07-19T09:46:08.017 回答
2

在尝试了所有没有结果的解决方案之后,这对我有用。

希望它会帮助某人

$data = str_replace('&quot;', '"', $data);
于 2018-10-15T07:19:44.263 回答
2

我有同样的问题。我采取了以下步骤:

  1. 更改了 JSON 文本编码

    $json = utf8_encode($json);
    
  2. 然后我在解码之前查看了纯文本。我发现了像这样的疯狂符号

    ï

  3. 然后我就把它剥掉了

    $json = str_replace(array('ï',''), '',$json);
    

    我成功解码了我的 JSON

于 2019-03-30T02:36:30.080 回答
1

您还没有显示您的 JSON,但这听起来可能是参数中的无效 UTF-8 序列,大多数在线验证器不会捕捉到它。确保您的数据是 UTF-8 并检查您是否有外来字符。你不需要 PHP5 来查看你的错误,使用error_log()来记录问题。

于 2013-06-20T17:30:34.687 回答
1

我也遇到了这个问题,这让我很沮丧。经过数小时在互联网上尝试不同的解决方案。我注意到文件的编码是带有 BOM 的 UTF-8,因为 var_dump() 正在回显一个奇怪的字符 在 JSON 之前。

我将我正在使用的 sample.json 文件从带有 BOM的 UTF-8转换为UTF-8 ...在 VS CODE 中将以下内容添加到您的 settings.json 或确保以下设置代码如下所示(以便任何默认情况下,您创建的文件将以 UTF-8 编码;

"files.encoding": "utf8",

然后你会在你的 VSCode 工具栏上看到类似下面的截图。(为了json_decode()工作,文件必须以 UTF-8 编码)

在此处输入图像描述

但在我的情况下,我创建的 JSON 文件有一个带有 BOM编码的 UTF-8,这就是为什么当我这样做json_decode($json, true)时返回 null(当我出现语法错误时var_dump(json_last_error_msg())

在此处输入图像描述

  1. 单击带有 BOM 的 UTF-8,然后您将获得下拉菜单,
  2. 单击使用编码保存
  3. 你应该得到下面的截图,然后你点击UTF-8

在此处输入图像描述

这将使用 UTF-8 编码重新保存您的文件,您可以继续检查您的代码。json_decode()会正常工作。不敢相信我花了几个小时试图找出可能出了什么问题。

快乐编码!

于 2020-11-20T04:20:00.967 回答
1

请先清理 json 数据,然后加载。

于 2019-09-28T08:37:44.580 回答
0

我遇到了同样的问题,原因是响应的文本看起来像 json,但它实际上是 HTML 格式的文本。您可以以 JSON 格式回显您的文本(类似 json 的),以查看其中的实际内容:

$response = file_get_contents('http://www.mywebservice');
header('Content-Type: application/json');
echo $response;

此函数file_get_contents将返回一些额外的 HTML 代码。就我而言,我删除了那些不需要的字符:

$response = str_replace('<head></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">', '',$response );
$response = str_replace('</pre></body>', '',$response );

这是完整的代码:

$response = file_get_contents('http://www.mywebservice');
$response = str_replace('<head></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">', '',$response );
$response = str_replace('</pre></body>', '',$response );
$response = json_decode($response);
header('Content-Type: application/json');            
$error = json_last_error_msg() ;
echo $error;

if ($error == null){echo "This is truly a JSON : <br>"}
echo $response;
于 2020-11-23T13:34:00.437 回答
0

JSON 字符串必须双引号,JSON 无效,因为您不需要转义'字符。

char = unescaped /
  escape (
      %x22 /          ; "    quotation mark  U+0022
      %x5C /          ; \    reverse solidus U+005C
      %x2F /          ; /    solidus         U+002F
      %x62 /          ; b    backspace       U+0008
      %x66 /          ; f    form feed       U+000C
      %x6E /          ; n    line feed       U+000A
      %x72 /          ; r    carriage return U+000D
      %x74 /          ; t    tab             U+0009
      %x75 4HEXDIG )  ; uXXXX                U+XXXX

'不在列表中。

请参阅 JSON 中使用的特殊字符列表:

\b  Backspace (ascii code 08)
\f  Form feed (ascii code 0C)
\n  New line
\r  Carriage return
\t  Tab
\"  Double quote
\\  Backslash character

查看站点以获取更多文档。

于 2019-09-28T09:04:02.460 回答
-1

我这边的一个问题是,有一些以 0 开头的无效数字,例如:“001”、“002”、“003”。

     "expectedToBeReturned":1,
     "inventoryNumber":001,
     "remindNote":"",

将 001 替换为 1 即可。

于 2019-08-07T14:46:13.367 回答
-1

这段代码对我有用。基本上它会删除隐藏的字符。

    function cleanString($val)
    {
        $non_displayables = array(
        '/%0[0-8bcef]/',            # url encoded 00-08, 11, 12, 14, 15
        '/%1[0-9a-f]/',             # url encoded 16-31
        '/[\x00-\x08]/',            # 00-08
        '/\x0b/',                   # 11
        '/\x0c/',                   # 12
        '/[\x0e-\x1f]/',            # 14-31
        '/x7F/'                     # 127
        );
        foreach ($non_displayables as $regex)
        {
            $val = preg_replace($regex,'',$val);
        }
        $search  = array("\0","\r","\x1a","\t");
        return trim(str_replace($search,'',$val));
    }
于 2019-09-28T07:59:21.690 回答
-2

我有同样的问题。对我来说,这是由echo "<br/><pre>".

我试图使用以下方法将 json 字符串传递给另一个 php 文件:

exit(json_encode(utf8ize($resp_array)));

在文件的开头,我已经取消了断行标记......所以这对我来说是错误的。删除此断行标记,我能够 [...]

于 2017-10-11T12:31:29.263 回答
-2

我有同样的问题。对我来说,这是由echo "<br/><pre>". 我试图将 json 字符串传递给另一个 php 文件,使用exit(json_encode(utf8ize($resp_array)));在文件的开头我已经取消了断行标记......所以这对我来说是错误的。删除这个断行标记,我能够将我的 json 字符串解码为另一个 php 文件。

于 2017-01-03T09:35:06.967 回答