删除PHP中的JSON数组元素,并重新编码为JSON

时间:2014-11-23 10:31:45

标签: php json

function deleteNews($selected) {
    $file = file_get_contents('news.json', true);

    $data=json_decode($file,true);
    unset($file);

foreach($selected as $index){
 unset($data[$index]);
 }


  $result=json_encode($data);

  file_put_contents('news.json', $result);
    echo $result;
    unset($result);
    $url="./deleteNews.php";
   //redirect($url);
    }

上述函数应该从JSON中删除条目,如:

[
     {
           "dummy":"dummy",
           "dummy1":"dumy"
      },
      {
           "dummy":"dummy1",
           "dummy1":"dummy"
      }
]

但最后该函数在JSON中插入数字索引,这是不可取的。

结果就像

[
    "0":
       {
          "dummy":"dummy",
          "dummy1":"dumy"
       },
     "1":
       {
           "dummy":"dummy1",
           "dummy1":"dummy"
       }
 ]

如何从中获取原始JSON格式?我不想要那个0 1 2索引部分。

N.B:执行此操作的foreach。如果没有foreach,则会按预期创建JSON。

3 个答案:

答案 0 :(得分:7)

TL; DR PHP数组,其中所有数字键从零开始已排序没有洞是唯一会被渲染成JSON数组[ "square", "brackets" ]的类型。所有其他类型将成为JSON词典{ "curly": "brackets" }


您观察到的行为的原因,以及array_values似乎解决问题的原因(以及案例,实际 ),在PHP和JSON数组和字典之间的区别。

这是一个带有连续数字键的PHP数组:

$a = array( "Apple", "Banana", "Canteloupe" );

这真的是

$a = array( 0 => "Apple", 1 => "Banana", 2 => "Canteloupe" );

在JSON中,这将成为数组

[ "Apple", "Banana", "Canteloupe" ]

这是一个带有文本键(哈希)的PHP数组:

$a = array( "a" => "Apple", "b" => "Banana", "c" => "Canteloupe" );

在JSON中,这是一个字典(注意大括号):

{ "a": "Apple", "b": "Banana", "c": "Canteloupe" }

某些操作会将PHP数组呈现为数组(ARA)更改为-rendered-as-dictionary(ARD)

这些操作是:

  • 将TEXT键添加到NUMERIC数组中。

  • 数字键不是不间断的已排序序列0 ... N。

所以这些似乎是数组,但实际上是词典

$a = array ( 2 => "Canteloupe", 1 => "Banana", 0 => "Apple" );

$a = array ( 0 => "Apple", 2 => "Canteloupe" );

$a = array ( 1 => "Banana", 0 => "Apple" );

这就是为什么删除一个不是最后一个的密钥会破坏你的数组并使其成为字典的原因:

0 1 2 3 => remove 3 => 0 1 2 => still an array!
0 1 2 3 => remove 2 => 0 1 3 => NOT an array!
0 1 2 3 => remove 2 => 0 1 3 => not an array => remove 3 => 0 1 => again an array!

如果您要将数组置于任何重新编号操作或array_values,您将再次获得纯数值数组:

/**
* delete news items given their index.
*
* @param array $selected     the list of indexes (e.g. [ 0, 1, 7 ])
* @return nothing
*/

function deleteNews(array $selected = [ ]) {
    try {
        $news = array_values( // Reorder...
            array_diff_key( // ...all keys...
                json_decode(file_get_contents('news.json', true), true), // ...in here...
                array_flip($selected) // ...that are not in $selected.
            )
        );
    } catch (\Exception $e) {
        // TODO handle errors (e.g. file not found and bad JSON)
    }
    try {
        file_put_contents('news.json', json_encode($news));
    } catch (\Exception $e) {
        // TODO handle errors
    }
    // $url="./deleteNews.php";
    // redirect($url);
}

因此,如果您的代码删除了数组的 last 索引,那么出现就会有效。一旦取消设置在数组中创建了一个洞,或者添加了一个文本键......

排序也是如此:[ 1 => "B", 0 => "A" ]是一个JSON字典。对它进行排序,保留与[ 0 => "A", 1 => "B" ]的关键关联,并成为JSON数组。

有关您的代码需要注意的一点是:您阅读" news.json"将include-path设置为 true 。但是然后将其保存到当前目录中。如果你有" news.json"在路径中的任何其他位置(当前目录除外),您最终将拥有两个 news.json文件;然后使用这两者中的哪一个取决于包含路径本身。

本地文件和安全性

保存本地文件(正如news.json所示)是可以的,但通常需要采取一些预防措施。

一般来说,最好放置这样的"变量"文件在他们自己的目录中(例如" ./ cache"或" ./ temp")与合适的.htaccess以防止直接阅读/执行,除非它'需要,以便可以更清楚地执行权限。

例如,可以使用" ./ data"目录,并将PHP文件其他地方设置为只读Web服务器;最后指示Apache Web服务器,以便这个目录在Web服务器可写时无法轻易用于利用系统:

<directory "/var/www/mysite/htdocs/data">
    # You CANNOT ask for /data and have a directory listing. Just in case.
    options      -Indexes
    # You CANNOT save "news.php" and have it executed :-)
    php_flag     engine     off
</directory>

这样,即使有人成功上传您系统上的文件并且该文件包含可执行的恶意PHP代码,也不允许执行该代码(至少不是直接执行)。

更多关于安全性:现实生活经验

允许直接访问受第三方控制的文件,甚至是间接访问始终有潜在危险 - 如果不是其他。例如,使用在第三个站点上收集的信息存储JSON对象。我刚刚在客户的网站上完成了一次成功的攻击测试。 Mutatis mutandis

  • 我在自己的网站上设置了一个包含精心制作数据的页面。
  • 我使用我的帐户登录WWW.CLIENT(好的,所以我留下了痕迹......)
  • 我指示WWW.CLIENT访问EVIL.COM并获取数据
  • 从我自己的帐户中我可以看到WWW.CLIENT上呈现的内容,具体取决于转义码,格式错误的UTF8字符和其他技巧
  • 最后(1)我能够注入命令来加载类似CDN的Javascript文件(驻留在EVIL.COM上)并让它在WWW.CLIENT的安全上下文中执行(2)
  • 经过几次诡计之后,我能够将WWW.CLIENT的客户(当然还有我的测试帐户)引导到WWW.CLIENT上精心设计的链接,该链接将默默地向客户提供EVIL.COM&#39 ; s认证令牌(3),(4)允许(例如)通过删除他的商品,添加我自己的商品以及更改送货地址来修改现存订单(5)。

这总共利用了五个安全漏洞(例如4:身份验证令牌没有链接到所有者的IP地址,或者没有在每次交易时重新生成,而5:对发票或交付的更改没有触发重新输入信用卡信息的请求)。虽然你可能认为这样的安全漏洞,安全漏洞,以及客户端都没有意识到它们,但它们实际上是已知功能,有设计,以&#34;可用性&#为名34;和&#34;用户便利&#34;。缺陷2源于在辅助图书馆中使用eval()的邪恶建议,这种图书馆不希望很快改变。最后,改变本地数据存储能力(缺陷1)很可能是唯一干预,我能够真实地向这个特定客户销售。

答案 1 :(得分:3)

尝试使用array_values:

$result = json_encode(array_values($data));

答案 2 :(得分:0)

function deleteNews($ selected){     $ file = file_get_contents('news.json',true);

$data=json_decode($file,true);
unset($file);

foreach($selected as $index){
  unset($data[$index]);
}

foreach($data as $value){
  $new_data[] = $value;
}

$result=json_encode($new_data);

file_put_contents('news.json', $result);
echo $result;
unset($result);
$url="./deleteNews.php";

//重定向($网址);  }