Ответ 1
HTTP-сжатие (т.е. gzip или deflate) уже делает именно это. Повторяющиеся шаблоны, такие как ваши JSON-ключи, заменяются токенами, так что подробный шаблон должен появляться только один раз для каждой передачи.
В настоящее время я разрабатываю веб-приложение и использую JSON для запросов и ответов ajax. У меня есть область, где я возвращаю очень большой набор данных клиенту в виде массива из более чем 10000 объектов. Здесь часть примера (его было несколько упрощено):
"schedules": [
{
"codePractice": 35,
"codeScheduleObject": 576,
"codeScheduleObjectType": "",
"defaultCodeScheduleObject": 12,
"name": "Dr. 1"
},
{
"codePractice": 35,
"codeScheduleObject": 169,
"codeScheduleObjectType": "",
"defaultCodeScheduleObject": 43,
"name": "Dr. 2"
},
{
"codePractice": 35,
"codeScheduleObject": 959,
"codeScheduleObjectType": "",
"defaultCodeScheduleObject": 76,
"name": "Dr. 3"
}
]
Как вы можете себе представить, с очень большим количеством объектов в этом массиве размер ответа JSON может быть довольно большим.
Мой вопрос в том, есть ли синтаксис/парсер JSON, который преобразует массив "schedules"
, чтобы выглядеть примерно так, как строка JSON:
"schedules": [
["codePractice", "codeScheduleObject", "codeLogin", "codeScheduleObjectType", "defaultCodeScheduleObject","name"],
[35, 576, "", 12, "Dr. 1"],
[35, 169, "", 43, "Dr. 2"],
[35, 959, "", 76, "Dr. 3"],
]
т.е. что в начале массива "schedules"
будет массив, в котором хранятся ключи объектов этого массива, и все остальные массивы контейнеров будут удерживать значения.
Я мог бы, если бы захотел, сделать преобразование на сервере и проанализировать его на клиенте, но мне интересно, есть ли стандартная библиотека для синтаксического анализа/стробирования большого JSON?
Я мог бы также запустить его через minifier, но я бы хотел сохранить ключи, которые у меня есть, поскольку они дают некоторый контекст в приложении.
Я также надеюсь, что вы можете критиковать мой подход здесь или предложить альтернативы?
HTTP-сжатие (т.е. gzip или deflate) уже делает именно это. Повторяющиеся шаблоны, такие как ваши JSON-ключи, заменяются токенами, так что подробный шаблон должен появляться только один раз для каждой передачи.
Вот статья, в которой вы многое делаете:
http://stevehanov.ca/blog/index.php?id=104
На первый взгляд, похоже, что ваш пример будет сжиматься до следующего после первого шага алгоритма, который на самом деле будет работать над ним на последующих шагах):
{
"templates": [
["codePractice", "codeScheduleObject", "codeScheduleObjectType", "defaultCodeScheduleObject", "name"]
],
"values": [
{ "type": 1, "values": [ 35, 576, "", 12, "Dr. 1" ] },
{ "type": 1, "values": [ 35, 169, "", 43, "Dr. 2" ] },
{ "type": 1, "values": [ 35, 959, "", 76, "Dr. 3" ] }
]
}
Вы уже можете увидеть преимущество алгоритма. Здесь конечный выход после запуска через компрессор:
{
"f" : "cjson",
"t" : [
[0,"schedules"],
[0,"codePractice","codeScheduleObject","codeScheduleObjectType","defaultCodeScheduleObject","name"]
],
"v" : {
"" : [ 1, [
{ "" : [2, 35, 576, "", 12, "Dr. 1"] },
{ "" : [2, 35, 169, "", 43, "Dr. 2"] },
{ "" : [2, 35, 959, "", 76, "Dr. 3"] }
]
]
}
}
Очевидно, можно увидеть улучшение, если у вас несколько тысяч записей. Выход по-прежнему доступен для чтения, но я думаю, что другие ребята тоже правы: хороший алгоритм сжатия будет удалять блоки текста, которые повторяются в любом случае...
Не ответ, но дать приблизительную оценку "сбережений" на основе 10 тыс. записей и некоторых фиктивных данных:-) Это в ответ на комментарий, который я разместил. Будет ли добавленная сложность сделать подход, основанный на схеме?
"Это зависит".
Этот С# является LINQPad и готов к тестированию/модификации:
string LongTemplate (int n1, int n2, int n3, string name) {
return string.Format(@"
{{
""codePractice"": {0},
""codeScheduleObject"": {1},
""codeScheduleObjectType"": """",
""defaultCodeScheduleObject"": {2},
""name"": ""Dr. {3}""
}}," + "\n", n1, n2, n3, name);
}
string ShortTemplate (int n1, int n2, int n3, string name) {
return string.Format("[{0}, {1}, \"\", {2}, \"Dr. {3}\"],\n",
n1, n2, n3, name);
}
string MinTemplate (int n1, int n2, int n3, string name) {
return string.Format("[{0},{1},\"\",{2},\"Dr. {3}\"],",
n1, n2, n3, name);
}
long GZippedSize (string s) {
var ms = new MemoryStream();
using (var gzip = new System.IO.Compression.GZipStream(ms, System.IO.Compression.CompressionMode.Compress, true))
using (var sw = new StreamWriter(gzip)) {
sw.Write(s);
}
return ms.Position;
}
void Main()
{
var r = new Random();
var l = new StringBuilder();
var s = new StringBuilder();
var m = new StringBuilder();
for (int i = 0; i < 10000; i++) {
var n1 = r.Next(10000);
var n2 = r.Next(10000);
var n3 = r.Next(10000);
var name = "bogus" + r.Next(50);
l.Append(LongTemplate(n1, n2, n3, name));
s.Append(ShortTemplate(n1, n2, n3, name));
m.Append(MinTemplate(n1, n2, n3, name));
}
var lc = GZippedSize(l.ToString());
var sc = GZippedSize(s.ToString());
var mc = GZippedSize(s.ToString());
Console.WriteLine(string.Format("Long:\tNormal={0}\tGZip={1}\tCompressed={2:P}", l.Length, lc, (float)lc / l.Length));
Console.WriteLine(string.Format("Short:\tNormal={0}\tGZip={1}\tCompressed={2:P}", s.Length, sc, (float)sc / s.Length));
Console.WriteLine(string.Format("Min:\tNormal={0}\tGZip={1}\tCompressed={2:P}", m.Length, mc, (float)mc / m.Length));
Console.WriteLine(string.Format("Short/Long\tRegular={0:P}\tGZip={1:P}",
(float)s.Length / l.Length, (float)sc / lc));
Console.WriteLine(string.Format("Min/Long\tRegular={0:P}\tGZip={1:P}",
(float)m.Length / l.Length, (float)mc / lc));
}
Мои результаты:
Long: Normal=1754614 GZip=197053 Compressed=11.23 % Short: Normal=384614 GZip=128252 Compressed=33.35 % Min: Normal=334614 GZip=128252 Compressed=38.33 % Short/Long Regular=21.92 % GZip=65.09 % Min/Long Regular=19.07 % GZip=65.09 %
Вывод:
Счастливое кодирование.
Прежде чем менять схему JSON, сделайте снимок
Для записи, я делаю именно это в php. Его список объектов из базы данных.
$comp=base64_encode(gzcompress(json_encode($json)));
json: строка (длина 22501)
gz Сжатый = строка (711), но его двоичный формат.
gz сжатый + base64 = строка (948) его текстовый формат.
Таким образом, его значительно меньше, используя долю секунды.