PHP json_decode()在看似有效的JSON中返回NULL?

171

我有一个存储在纯文本文件中的JSON对象:

{
    "MySQL": {
        "Server": "(server)",
        "Username": "(user)",
        "Password": "(pwd)",
        "DatabaseName": "(dbname)"
    },
    "Ftp": {
        "Server": "(server)",
        "Username": "(user)",
        "Password": "(pwd)",
        "RootFolder": "(rf)"
    },
    "BasePath": "../../bin/",
    "NotesAppPath": "notas",
    "SearchAppPath": "buscar",
    "BaseUrl": "http:\/\/montemaiztusitio.com.ar",
    "InitialExtensions": [
        "nem.mysqlhandler",
        "nem.string",
        "nem.colour",
        "nem.filesystem",
        "nem.rss",
        "nem.date",
        "nem.template",
        "nem.media",
        "nem.measuring",
        "nem.weather",
        "nem.currency"
    ],
    "MediaPath": "media",
    "MediaGalleriesTable": "journal_media_galleries",
    "MediaTable": "journal_media",
    "Journal": {
        "AllowedAdFileFormats": [
            "flv:1",
            "jpg:2",
            "gif:3",
            "png:4",
            "swf:5"
        ],
        "AdColumnId": "3",
        "RSSLinkFormat": "%DOMAIN%\/notas\/%YEAR%-%MONTH%-%DAY%\/%TITLE%/",
        "FrontendLayout": "Flat",
        "AdPath": "ad",
        "SiteTitle": "Monte Maíz: Tu Sitio",
        "GlobalSiteDescription": "Periódico local de Monte Maíz.",
        "MoreInfoAt": "Más información aquí, en el Periódico local de Monte Maíz.",
        "TemplatePath": "templates",
        "WeatherSource": "accuweather:SAM|AR|AR005|MONTE MAIZ",
        "WeatherMeasureType": "1",
        "CurrencySource": "cotizacion-monedas:Dolar|Euro|Real",
        "TimesSingular": "vez",
        "TimesPlural": "veces"
    }
}
当我尝试使用 json_decode() 解码它时,返回了 NULL。为什么会这样呢?文件是可读的(我尝试使用 file_get_contents() 输出并且可以正常工作)。我已经在 http://jsonlint.com/ 进行了 JSON 验证,它是完全有效的。这里出了什么问题?

7
我正在使用 PHP 5.2.9,因此无法使用 json_last_error() - Joel A. Villarreal Bertoldi
1
还要注意的是,文件中间可能存在其他无效字符导致这种情况发生。我曾经遇到过json_decode()返回null的情况,因为字符串包含一个特殊的en-dash,可能是从MS Word复制粘贴而来,然后可能出现了误编码。为了识别潜在的问题字符,打开JSON文件(我用的是Notepad++),更改编码(不要进行转换),并另存为副本。然后比较两个文件的差异(我使用的是WinMerge)。 - LinusR
(Windows 记事本问题)请参考此链接,我也遇到了同样的问题,通过这个链接解决了:https://dev59.com/y2kv5IYBdhLWcg3w4kl2 - Felix Aballi
可能是重复的问题:json_decode 在调用 Web 服务后返回 NULL - user
对我来说,这并不是什么特别的事情,只是一个对象元素末尾多了一个逗号而已。重点是:任何使您的 JSON 不一致的因素都会引发错误。额外提示:不要相信 jsonviewer.stack.hu,使用类似 jsonlint 的工具。 - Aman Alam
@Cristik 问我在11年后编辑问题有点有趣,哈哈。无论如何,我会进行编辑以澄清。 - Joel A. Villarreal Bertoldi
29个回答

134

这对我起作用了

json_decode( preg_replace('/[\x00-\x1F\x80-\xFF]/', '', $json_string), true );

4
我使用了这个方法得到了数组,但是我的语言特定字符(如ş、ç、ö等)也被删除了。 - zkanoca
14
如果JSON数据是UTF-8编码(或者我猜任何UTF编码),那么这个做法是不正确的,它会移除有效的UTF-8编码数据。如果文件只包含英语,那么它可能能够正常工作,但这种假设总是存在风险的。我不建议使用这种方法。 - DaedalusAlpha
有了这个它可以工作,但没有它就不行,尽管这两个字符串是相同的,我是不是漏掉了什么? - Rudie Visser
2
它确实起作用了!但为什么?我尝试解码的字符串中没有任何特殊字符。 - Tobias Gassmann
这将从英文翻译成中文。仅返回翻译后的文本:这也会删除波斯/阿拉伯字符。我希望它们能够包含在JSON中。有什么建议吗? - undefined

96

可能是特殊字符的编码问题。您可以使用 json_last_error() 方法获取明确的信息。


1
不错,这应该可以工作。我现在无法进行更多的测试,如果以后有机会我会在这里发布。用户贡献的注释中也有一些提示:http://de.php.net/json_decode 或许有些东西能帮到你。 - Pekka
1
对我来说,在 PHP 5.3 上,当文本编码为 UTF-8 时,它可以正常工作。但是如果我首先通过 utf8_decode() 传递文本,然后 json_decode() 就会悄悄失败。 - Matthew
已检查文件编码,它是UTF-8。由于我的应用程序完全基于UTF-8工作,因此无需解码。 - Joel A. Villarreal Bertoldi
2
@Pekka 在谷歌上寻找答案后,我回到了SO:https://dev59.com/questions/_HRB5IYBdhLWcg3wNk53。我的JSON文件有UTF BOM序列(一些不应该存在的二进制字符),因此破坏了JSON结构。我去了十六进制编辑器,擦除了这些字节。一切都恢复正常了。为什么会发生这种情况?因为我使用微软Windows的记事本编辑了文件。可怕的想法! - Joel A. Villarreal Bertoldi
2
应该向 PHP 开发团队报告这个问题。如果 BOM 是有效的 UTF8 编码,它不应该默默地阻塞。 - jmucchiello
显示剩余6条评论

61

你可以尝试一下。

json_decode(stripslashes($_POST['data']))

27

如果你在Chrome中检查请求,你会发现JSON是文本格式的,因此已经添加了空白代码到JSON中。

你可以通过使用

$k=preg_replace('/\s+/', '',$k);

来清除它。

然后你可以使用:

json_decode($k)

print_r 将会显示数组。


1
为我解决了问题! 我做了一个简单的调整,就是在替换中添加了一个空格。我正在使用这个方法,它似乎也替换了我的空格。现在运行得很好。 $k=preg_replace('/\s+/', ' ',$k); - Kash
2
问题在于,这样会删除每一个空格,使得英文文章都连接到一起了,是吧? - CodeGuru

27

也许一些隐藏的字符正在干扰您的JSON,请尝试以下方法:

$json = utf8_encode($yourString);
$data = json_decode($json);

16

我曾经遇到同样的问题,简单地通过在解码之前替换引号字符来解决了这个问题。

$json = str_replace('"', '"', $json);
$object = json_decode($json);

我的JSON数值是由JSON.stringify函数生成的。


在这种情况下,可能使用了函数htmlspecialchars,导致JSON无法再解析。为了将其反转,可以使用函数“htmlspecialchars_decode”,而不是手动替换"。 - Davy

9

我在接收来自JavaScript的JSON时使用php函数stripslashes(),而在接收来自Python的JSON时,json_decode调用的第二个可选参数起到了作用,因为数组是关联性的。这对我非常好用。

$json = stripslashes($json); //add this line if json from javascript
$edit = json_decode($json, true); //adding parameter true if json from python

8

这个错误意味着你的 JSON 字符串不是有效的 JSON!

启用异常抛出功能可以在发生错误时抛出一个带有失败原因的异常。

使用以下代码:

$json = json_decode($string, null, 512, JSON_THROW_ON_ERROR);

6

我想在这里补充一下,因为我今天遇到了这个问题。如果您的JSON字符串周围有任何字符串填充,则json_decode将返回NULL。

如果您从除PHP变量以外的源中提取JSON,则最好先进行“修剪”:

$jsonData = trim($jsonData);

6
这将帮助您了解错误类型。
<?php
// A valid json string
$json[] = '{"Organization": "PHP Documentation Team"}';

// An invalid json string which will cause an syntax 
// error, in this case we used ' instead of " for quotation
$json[] = "{'Organization': 'PHP Documentation Team'}";


foreach ($json as $string) {
    echo 'Decoding: ' . $string;
    json_decode($string);

    switch (json_last_error()) {
        case JSON_ERROR_NONE:
            echo ' - No errors';
        break;
        case JSON_ERROR_DEPTH:
            echo ' - Maximum stack depth exceeded';
        break;
        case JSON_ERROR_STATE_MISMATCH:
            echo ' - Underflow or the modes mismatch';
        break;
        case JSON_ERROR_CTRL_CHAR:
            echo ' - Unexpected control character found';
        break;
        case JSON_ERROR_SYNTAX:
            echo ' - Syntax error, malformed JSON';
        break;
        case JSON_ERROR_UTF8:
            echo ' - Malformed UTF-8 characters, possibly incorrectly encoded';
        break;
        default:
            echo ' - Unknown error';
        break;
    }

    echo PHP_EOL;
}
?>

1
自 PHP 5.5.0 起,您可以使用 json_last_error_msg 方法来获取一条相对有用的消息。 - Tomás Cot

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接