json_decode返回JSON_ERROR_SYNTAX但在线格式化程序说JSON没问题

时间:2013-06-20 17:22:08

标签: php json

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

我有一个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;
}

我收到错误:SYNTAX ERROR

一切都没有完全帮助。

这是一场噩梦。

我看到使用PHP 5.5我可以使用此功能:http://php.net/manual/en/function.json-last-error-msg.php

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

17 个答案:

答案 0 :(得分:72)

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

<?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);
?>

答案 1 :(得分:41)

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

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

你不应该有一张BOM,但如果它有,那就是看不见的,所以你不会看到它!!

请参阅W3C on BOM's in HTML

如果您要修复很多文件,请

使用BOM Cleaner

答案 2 :(得分:27)

我解决了这个问题,在json_decode之前将 stripslashes 添加到字符串中。

$data = stripslashes($data); 
$obj = json_decode($data);

答案 3 :(得分:6)

为了把所有东西放在一起,我已经准备好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;

答案 4 :(得分:2)

就我而言:

json_decode(html_entity_decode($ json_string));

答案 5 :(得分:2)

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

答案 6 :(得分:1)

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

答案 7 :(得分:1)

我也面临这个问题,这让我感到沮丧。经过数小时尝试在互联网上使用其他解决方案。我注意到文件的编码是在 UTF-8中且带有BOM ,因为var_dump()在JSON之前回显了一个奇怪的字符&#65279;

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

"files.encoding": "utf8",

然后,您将在VSCode工具栏上看到类似以下屏幕截图的内容。 (要使json_decode()正常工作,文件必须使用UTF-8编码)

enter image description here

但是在我的情况下,我创建的JSON文件使用的是 UTF-8和BOM 编码,这就是为什么当我执行json_decode($json, true)时它返回null(当我出现语法错误时var_dump(json_last_error_msg())

enter image description here

  1. 点击带有BOM的 UTF-8 ,然后您将获得下拉列表,
  2. 点击使用编码保存
  3. 您应该获得以下屏幕截图,然后单击 UTF-8

enter image description here

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

快乐编码!

答案 8 :(得分:1)

尝试了所有解决方案但没有结果之后,这对我来说就是一个解决方法。

希望它将对某人有所帮助

$data = str_replace('&quot;', '"', $data);

答案 9 :(得分:1)

我遇到了同样的问题,收到了 JSON_ERROR_CTRL_CHAR JSON_ERROR_SYNTAX
这是我的解决方法。

$content = json_decode(json_encode($content), true);

答案 10 :(得分:1)

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

访问this网站以获取更多文档。

答案 11 :(得分: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;

答案 12 :(得分:0)

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

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

答案 13 :(得分:0)

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

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

将001替换为1即可。

答案 14 :(得分:0)

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

  1. 更改了JSON文本编码

    $json = utf8_encode($json);
    
  2. 然后我在解码之前查看了纯文本。我发现了

    这样的疯狂符号

    ï

  3. 然后我将其剥离

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

    我成功解码了JSON

答案 15 :(得分:-1)

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

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

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

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

答案 16 :(得分:-1)

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