我目前正在开发一个Web应用程序,并使用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的标准库?
我也可以通过缩小器来运行它,但是我想保留我目前的密钥,因为它们在应用程序中提供了一些上下文。
我也希望你可以在这里批评我的方法或建议替代方案?
答案 0 :(得分:11)
HTTP压缩(即gzip或deflate)已经完全正确。重复的模式(如JSON密钥)将替换为标记,以便每次传输时只需要进行一次详细模式。
答案 1 :(得分:7)
不是答案,而是基于10k条目和一些虚假数据粗略估计“节省”:-)这是对我发布的评论的回应。增加的复杂性是否会使模式化方法值得?
“这取决于。”
这个C#是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 %
结论:
快乐的编码。
答案 2 :(得分:6)
这篇文章几乎完成了你想要做的事情:
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"] }
]
]
}
}
如果您有数千条记录,显然可以看到改进。输出仍然是可读的,但我认为其他人也是对的:一个好的压缩算法将删除无论如何重复的文本块...
答案 3 :(得分:3)
在更改JSON架构之前,请先尝试一下
答案 4 :(得分:0)
为了记录,我正在用PHP完成它。它是数据库中的对象列表。
import {AbstractControl, ValidatorFn} from '@angular/forms';
export function confirmPasswordValidator(): ValidatorFn {
return (control: AbstractControl) => {
const pswd = control.value;
const passwordConfirm = control.root.value.verification.password;
return (pswd === passwordConfirm) ? null : {'strongPasswordError': {pswd}};
};
}
json:string(22501 length)
gz compressed = string(711)但它是二进制格式。
gz compressed + base64 = string(948)是一种文本格式。
所以,通过使用一小部分秒,它相当小。