如何将大对象/数组序列化为JSON

时间:2014-01-09 13:12:30

标签: php arrays json zend-framework spl

我的应用程序需要生成一个对象的json,该对象具有类型为array的大data属性。数组需要在收集数据库输出时保留在内存中,并且只有在数组完成后才能确定某些属性。

复杂化:数组是基于数字的,并且必须在json输出中显示,因此直接json_encode()不是一个选项。

为了在像RasPi这样的低规格机器上实现这一点,我研究了修剪内存消耗:

  1. 使用SPLFixedArray
  2. 使用stringpack()
  3. 这两种方法都会处理数组存储内存问题,但在使用JSON进行编码时会失败。

    我已经研究过实现JsonSerializable但是因为它迫使用户返回结果,然后在Json中编码我回到

    public function jsonSerialize() {
        return $this->toArray();
    }
    

    具有相同的内存问题。

    zendframework/Component_ZendJson看起来很有前途,因为它会查找具有toJson()方法的对象,以便将自己的编码提供为string而不是object

    我想知道是否有更好的选项不会给出内存问题?

2 个答案:

答案 0 :(得分:5)

在我的调查中,我研究了5种不同的方法,用于在内存中存储大量元组,在此总结其结果(以50k记录采样):

  1. 幼稚

    json_encode使用array(array(), array())

    导出json非常简单

    内存:18.5MB(巨大
    时间:〜100ms构建和转储阵列(Windows PC)

  2. SPL资料库

    此方法将所有内容存储在嵌套SPLFixedArraysSPLFixedArray[SPLFixedArray]中。通过实施Zend\Json\Encoder方法,JSON导出扩展了toJson

    内存:15.5MB(仍然很大
    时间:~1.3s,x10慢

  3. SPL图书馆

    与2类似,但不是内部SPLFixedArray使用来自PHP的pack()函数的压缩字符串。

    内存:3.5MB(小5倍
    时间:~1.3s,x10较慢 - 显然pack()与嵌套数组一样慢。

  4. SPL图书馆

    与2类似,但不是内部SPLFixedArray,而是将实际元组简单地写为根数组的顺序值。

    内存:3.25MB(再次更小
    时间:约0.7秒,只有x6慢 - 我们在这里有赢家吗?

  5. pack()

    与3类似,但使用PHP的SPLFixedArray函数将所有内容打包到单个字符串中,而不是根pack()。这显然需要了解各个阵列的固定,相同结构。

    内存:1.25MB(非常小 - 仅为原始内存的1/12
    时间:~1.7s,x16慢

  6. 结论

    虽然(5)提供了最佳的内存利用率,但它也非常慢。出于我的目的,我已经确定了(4)这约占原始内存消耗的20%但是 - 当考虑JSON编码时 - 也慢了5~6倍。可接受的妥协。

答案 1 :(得分:-1)

根据json.org

  

JSON基于两种结构:

     
      
  • 名称/值对的集合。在各种语言中,这被实现为对象,记录,结构,字典,哈希表,键控   列表或关联数组。
  •   
  • 有序的值列表。在大多数语言中,这被实现为数组,向量,列表或序列。
  •   

我不知道是否存在内存问题,但请考虑以下代码:

<?php
// No declared index causes no index in JSON
$arr = array('dssdf','38904uj');
echo json_encode($arr).'<br><br>';
// ["dssdf","38904uj"]

// start array at 0 removes the index from JSON
$arr = array('0'=>'dssdf','1'=>'38904uj');
echo json_encode($arr).'<br><br>';
// ["dssdf","38904uj"]

// start array at 1 forces the index to show in JSON
$arr = array('1'=>'dssdf','2'=>'38904uj');
echo json_encode($arr).'<br><br>';
// {"1":"dssdf","2":"38904uj"}

// skip an index forces the index to show in JSON
$arr = array('0'=>'dssdf','1'=>'38904uj','3'=>'321as5d4');
echo json_encode($arr).'<br><br>';
// {"0":"dssdf","1":"38904uj","3":"321as5d4"}

// JSON_FORCE_OBJECT option forces indexes
$arr = array('0'=>'dssdf','1'=>'38904uj');
echo json_encode($arr, JSON_FORCE_OBJECT).'<br><br>';
// {"0":"dssdf","1":"38904uj"}
?>