2014-01-09 3 views
1

Мое приложение должно создавать json объекта с большим свойством data типа массива. Массив должен оставаться в памяти, когда он собирает вывод DB, а некоторые свойства могут быть определены только после завершения массива.Как сериализовать большие объекты/массивы в JSON

Усложнение: массив численно основан и должен отображаться как таковой на выходе json, поэтому прямой json_encode() не является вариантом.

Чтобы сделать это возможным на низкой спецификации машин, как RasPi я заглянула в подстроечного потребление памяти:

  1. Использование SPLFixedArray
  2. Использование string и pack()

Оба подхода заботиться о проблема с памятью массива, но с ошибкой, когда дело доходит до кодирования в JSON.

Я посмотрел в реализации JsonSerializable, но как это вынуждает пользователей возвращать результат, который затем закодированный в Json я вернулся к

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

, который имеет те же проблемы с памятью.

zendframework/Component_ZendJson выглядит многообещающим, как это выглядит для объектов, имеющих метод toJson(), чтобы обеспечить свою собственную кодировку, string вместо object.

Мне интересно, есть ли лучшие варианты, которые не дают проблем с памятью?

+0

Я уверен, что то, что вы делаете, намного выше моей головы, но PHP изначально имеет ** [json_encode] (http://us2.php.net/json_encode) **. Если он не применяется, я могу удалить этот комментарий =) – MonkeyZeus

+0

Хороший улов. Разумеется, есть причина, о которой я забыл упомянуть. Облом. Осложнение: массив основан на численном выражении и должен отображаться как таковой в выводе json, поэтому прямой 'json_encode()' не является опцией. – andig

+0

Это? http://stackoverflow.com/a/4844309/46675 –

ответ

4

В моем исследовании я смотрел на 5 различных подходов для хранения больших массивы кортежей в памяти, обобщенные здесь с их результатами (отбираются при 50 тыс. записей):

  1. Наивные

    Экспорт JSON прост с json_encode использованием array(array(), array())

    Память: 18.5MB (огромный)
    Время: ~ 100ms, чтобы построить и сбрасывают массив (ПК с Windows)

  2. Библиотека SPL

    Этот подход хранит все в вложенных SPLFixedArrays: SPLFixedArray[SPLFixedArray]. Экспорт JSON был выполнен с использованием Zend\Json\Encoder путем реализации метода toJson.

    Память: 15.5MB (еще большая)
    Время: ~ 1.3s, x10 медленнее

  3. SPL Библиотека

    Аналогично 2, но вместо внутреннего SPLFixedArray использует упакованные строки из РНР pack() функция.

    Память: 3.5MB (5 разы меньше)
    Время: ~ 1.3s, x10 медленнее - по-видимому, pack() аналогично замедлятся, как вложенный массив.

  4. SPL Библиотека

    Аналогично 2, но вместо внутреннего SPLFixedArray фактического кортежи просто записывается в виде последовательных значений в корневой массив.

    Память: 3.25MB (снова меньше)
    Время: ~ 0.7s, только x6 медленнее - у нас есть победитель здесь?

  5. pack()

    Подобно 3, но вместо того, чтобы корневой SPLFixedArray упаковать все в одну строку с помощью pack() функции РНР. Это, очевидно, требует знания и фиксированной идентичной структуры отдельных массивов.

    Память: 1.25MB (очень маленькая - только 1/12 оригинальной память)
    Времени: ~ 1.7s, х16 медленнее

ЗАКЛЮЧЕНИЕ

В то время как (5) предлагает лучшее использование памяти это также очень медленно. Для моих целей я решил (4), что составляет около 20% от исходного потребления памяти, но когда учитывается кодировка JSON, также в 5-6 раз медленнее. Приемлемый компромисс.

+0

один из лучших и наиболее полных ответов. –

0

По 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"} 
?> 
Смежные вопросы