【问题标题】:Odd Behavior when appending JSON file using PHP使用 PHP 附加 JSON 文件时的奇怪行为
【发布时间】:2013-12-08 15:42:57
【问题描述】:

所以我有一个 JSON 文件,其中包含以下格式的篮球运动员信息:

[{"name":"Lamar Patterson","team":1,"yearsLeft":0,"position":"PG","PPG":17},{"name":"Talib Zanna", "team":1,"yearsLeft":0,"position":"SF","PPG":13.1},....]

我希望用户能够将自己的自定义播放器添加到此文件中。为此,我尝试以下方法:

<?php 
        $json = file_get_contents('json/players.json');
        $info = json_decode($json, true);
        $info[] = array('name'=>$name, 'team'=>$team, 'yearsLeft'=>4, 'position'=>$position, 'PPG'=>$ppg);
        file_put_contents('json/players.json', json_encode($info));
    ?>

这种“有点”有效。但是当我检查 JSON 文件时,我发现有 3 个新条目而不是 1 个:

{"name":"","team":null,"yearsLeft":4,"position":"","PPG":""},{"name":"","team":"3","yearsLeft":4,"position":"","PPG":""},{"name":"Jeff","team":null,"yearsLeft":4,"position":"C","PPG":"23"}

假设 $name="Jeff" $team=3 和 $ppg=23(通过 POST 提交填充)。

发生了什么,我该如何解决?

【问题讨论】:

  • 你确定源文件是正确的吗?没有逗号之类的?
  • 你在用ajax做POST吗?一些双击可能会触发额外的条目。只是为了确定
  • 您确定没有竞争条件发生,例如多人同时添加记录?我无法重现您的问题。 $name等在哪里设置?

标签: php json post


【解决方案1】:

您可以尝试执行以下操作:

未经测试的代码

<?php
if(!empty($name) && !empty($team) && !empty($position) && !empty($ppg)) {
    $fh = fopen('json/players.json', 'r+') or die("can't open file");
    $stat = fstat($fh);
    ftruncate($fh, $stat['size']-1);//removes last ] char
    fclose($fh); 
    $fh = fopen('json/players.json', 'a');
    $info = array('name'=>$name, 'team'=>$team, 'yearsLeft'=>4, 'position'=>$position, 'PPG'=>$ppg);
    fwrite($fh, ','.json_encode($info).']');
    fclose($fh);
}
?>

这会将唯一的新 json 附加到文件中,而不是打开文件,使 php 解析所有 json,然后再次将其写入文件。除此之外,它只会在变量实际包含数据时存储数据。

【讨论】:

  • 这段代码首先效率更高,它可能会解决 php 的 json_decode 无法正确解释您的 json 数据的问题。
  • 有趣的是,这会导致同样的问题。问题可能在于这些变量在我的代码中的不同位置定义的事实吗?
  • 似乎随后对该脚本发出了多个发布请求。也许在存储数据之前尝试添加检查以查看 $name、$team、$position 和 $ppg 是否不为空。
  • ^ 就是这样。感谢您提供有关检查是否为空的提示!但是,我应该提到,这段代码在文件的结尾 ] 之后添加了 json 数组。它也不会在 } 和 { 之间添加逗号
  • 是的,没错,那么您可能确实想使用旧代码,只是检查它是否为空。然而,随着 json 文件变大,该代码会变慢。或者,您可以让脚本从文件中删除 ] 然后读取它。
【解决方案2】:

试试这个:

<?php
//get the posted values
$name = $_POST['name'];
$team = $_POST['team'];
$position = $_POST['position'];
$ppg = $_POST['ppg'];

//verify they're not empty
if(!empty($name) && !empty($team) && !empty($position) && !empty($ppg)) {
        //Open the file
        $fh = fopen('json/players.json', 'r+') or die("can't open file");

        //get file info/stats
        $stat = fstat($fh);

        //final desired size after trimming the trailing ']'
        $size = $stat['size']-1;

        //file has contents? then remove the trailing ']'
        if($size>0) ftruncate($fh, $size);

        //close the current handle
        fclose($fh);

        // reopen the file for append
        $fh = fopen('json/players.json', 'a');

        //build your data array
        $info = array('name'=>$name, 'team'=>$team, 'yearsLeft'=>4, 'position'=>$position, 'PPG'=>$ppg);
         //if this is not the first item on file
        if($size>0) fwrite($fh, ','.json_encode($info).']'); //append with comma
        else fwrite($fh, '['.json_encode($info).']'); //first item on file
        fclose($fh);
}
?>

也许您的 php 配置未设置为将 post/get 变量转换为全局变量。这发生在我身上几次,所以我宁愿创建我期望从 post/get 请求中得到的变量。还要注意页面编码,根据个人经验,您可能会在那里得到空字符串。

【讨论】:

  • 请使用$_POST 而不是$_REQUEST
  • 完成。你是对的,我挖掘 $_REQUEST 以防我试图在 GET 或 POST 上获取东西并且并不真正关心它们被发布在哪里。但这可能会导致其他问题。
猜你喜欢
  • 2014-10-09
  • 1970-01-01
  • 2011-05-06
  • 1970-01-01
  • 2022-01-11
  • 2012-12-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多