【问题标题】:PHP JSON parsing giving an errorPHP JSON解析给出错误
【发布时间】:2010-09-14 14:14:40
【问题描述】:

我正在尝试使用 PHP 解析 JSON 字符串,使用 jQuery $.ajax 以这种格式 [{"value":"59"},{"value":"7"},{"value":"46"}] 将 JSON 发送到 PHP 文件,但由于某些奇怪的原因,我不断收到此错误 "Invalid argument supplied for foreach()",在这里是我的 PHP 和 jQuery 代码,

jQuery:

    $(".systems").each( function(i, system) {
        // for each location block
        system = $(system);
        var sys = {
            'value' : $("select[data-prod='products']", system).val()
        };
        allSystems.push( sys );
    });

        $.ajax({
                type: 'POST',
                url: 'systems.php',
                dataType: 'json',
                data: { systems: JSON.stringify(allSystems), uid: uid },
                success: function(data){
                    alert(data)
                }
        });

PHP:

require_once 'classes/Zend/Json.php';

$json = $_POST['systems'];
$uid = $_POST['uid'];
$array= Zend_Json::decode("$json"); 

mysql_connect('localhost','user','pass') or die(mysql_error());
mysql_select_db('products') or die(mysql_error());

//insert the suppliers products into the database
foreach($array as $key){
    $query = mysql_query("INSERT INTO suppliersProducts (product_id, supplier_id) VALUES('".$key['value']."', '".$uid."' ) ") or die(mysql_error());
}

print_r($json);

如您所见,我正在使用 Zend 框架的 JSON 解码函数来解码传递给 PHP 的 JSON 字符串,并且格式对我来说似乎是正确的,所以我不知道还有什么可能导致此错误,也许编码?有什么想法吗?

提前谢谢!

【问题讨论】:

  • 在 $json 和 $test 上尝试var_dump 并发布它以开始使用...
  • 当我在$json 上执行var_dump 时,我得到这个string(19) "[{\"value\":\"6\"}]"$test 我得到NULL,我现在正在使用 Zend_Json::decode() 来解码 JSON ,当我用预先格式化的字符串测试它时,我得到了数组,但当我通过 ajax 传递 JSON 时却没有,所以我假设可能是传递的 JSON 格式不正确?跨度>
  • 来自同一用户的完全相同的副本:stackoverflow.com/questions/3707205/…

标签: php jquery ajax json


【解决方案1】:

看起来 json_decode() 无法处理该 post 参数中的数据。为您的脚本添加一些错误处理。

$test = json_decode($json, true);
if ( is_null($test) ) {
  die('data is not encoded as valid json');
}
else if ( !is_array($test) ) {
  die('Unexpected data structure. Array expected.');
}

您可能还对json_last_error()感兴趣


更新:可能是编码问题。由于您无权访问 json_last_error() 您可能需要“手动”检查字符串和编码,例如

if ( is_null($test) ) {
  // <--- for debugging purposes only
  echo '<pre>Debug: $json=';
  var_dump($json);
  echo 'hex=';
  for($i=0; $i<strlen($json); $i++) {
    printf('%02X ', ord($json[$i]));
  }
  echo '</pre>';
  // for debugging purposes only -->
  die('data is not encoded as valid json');

在将值作为字符串文字混合到 sql 语句中时,您还必须使用mysql_real_escape_string(),请参阅CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')

$mysql = mysql_connect('localhost','user','password') or die(mysql_error());
mysql_select_db('products', $mysql) or die(mysql_error($mysql));

...

$sql = "
  INSERT INTO
    suppliersProducts
    (product_id, supplier_id)
  VALUES
    (
      '" . mysql_real_escape_string($key['value'], $mysql) . "'
      , '" . mysql_real_escape_string($uid, $mysql) . "'
    )
";
$query = mysql_query($sql, $mysql) or die(mysql_error($mysql));

甚至更好:使用准备好的参数化查询,例如PDO - Prepared statements and stored procedures

【讨论】:

  • 我添加了错误处理,我得到了这个,“数据没有编码为有效的 json”,我刚和我的托管服务提供商谈过,他们说他们在 PHP 5.2.6 上,有吗有没有其他方法解决这个问题?
  • 嗯,那你就无权访问 json_last_error()。我的 guess 是编码有问题(json_decode() 需要 utf-8 编码)。查看更新....
【解决方案2】:

听起来$test 在您的其他服务器中并不是真正的数组,因此json_decode 可能没有返回数组。 json_decode 甚至在该服务器中可用吗?它仅在 php 5.2.0 之后可用。查看phpinfo()了解版本详情。

error_reporting(E_ALL)ini_set('display_errors', 1) 设置在顶部,以便在 foreach 之前看到任何错误。

【讨论】:

  • 服务器正在运行 5.2.6,但我仍然收到该死的错误!
【解决方案3】:

由于foreach() 仅适用于数组,因此在调用foreach() 之前,您应该使用is_array($test) 来检查您是否从json 中获得了一个数组。

【讨论】:

    【解决方案4】:
    当我对 $json 执行 var_dump 时,我得到这个字符串 (19) "[{\"value\":\"6\"}]"

    看起来magic_quotes_gpc 已开启。实际的 json 编码字符串将是 [{"value":"6"}],但由于可怕的魔术引号,所有双引号都被替换为 \" 这使得它对 json_decode() 无效。您可以使用 stripslashes() 来“扭转损坏”。

    $json = get_magic_quotes_gpc()
      ? stripslashes($_POST['systems']) : $_POST['systems'];
    

    【讨论】:

      【解决方案5】:

      检查 $test 和 $json 的值。 $json 似乎不是注释中所述的 JSON 数组,因此 $test 不会成为 PHP 数组。

      在 foreach 循环中使用 $test 之前,您应该检查它是否是一个数组。

      if(is_array($test)) {
        // proceed..
      }
      

      【讨论】:

        【解决方案6】:

        正如其他人所说,如果您尝试将 foreach() 与不是数组或根本未设置的变量一起使用,它将引发此错误,因此如果有可能发生这种情况,您应该检查 is_array( ) 在 foreach 循环之前。

        但是,我也想发布一个答案,以指出您看到的消息只是 PHP 中的警告级别消息。换句话说,您的程序在遇到此错误后将继续工作(它将跳过 foreach() 循环并继续执行)。此外,可以使用 PHP.ini 设置 PHP 以禁止显示警告消息(或实际上任何其他错误消息)。因此,有可能(例如,如果您对系统进行了更改,或者如果您在不同的系统上运行该程序)您可能一直遇到错误,但以前从未见过它。

        【讨论】:

          【解决方案7】:

          只需更改以下内容:

          $json = $_POST['systems']; 
          $uid = $_POST['uid'];
          $test = json_decode($json, true); 
          

          $json = !empty($_POST['systems']) ? json_decode($_POST['systems'], true) : array();
          $json = is_array($json) ? $json : array();
          
          $uid = $_POST['uid'];
          foreach($json as $key => $value)
          {
              //Less error prone.
          }
          

          【讨论】:

          • 这更好,但它仍然不是 $_POST['systems'] 包含一个 json 数组(它是一个 post 变量所以可以是任何东西),所以你仍然应该检查 is_array() 之前执行 foreach 循环。
          • 更新了第二行以解决 json 验证问题。
          【解决方案8】:

          在通过Zend_Json::decode() 解码之前,您是否检查过字符串的编码?这是一个常见问题 - 如果您将格式强制转换为例如 utf8(通过 utf8_encode()),它可能对您有用。

          【讨论】:

          • 不,我没有,我尝试强制编码,但没有运气,据我所知 $.ajax 在 utf8 中发布数据。
          【解决方案9】:

          您可能会尝试的一件事是,当您在 .each 循环中声明您的系统时,将值括在引号中。像这样的:

              var sys = {
                  'value' : "'" +  $("select[data-prod='products']", system).val() + "'"
              };
          

          PHP 解析器可能要求值用引号引起来

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-05-19
            • 2014-07-18
            • 1970-01-01
            • 1970-01-01
            • 2020-11-03
            • 1970-01-01
            相关资源
            最近更新 更多