当我们使用GET或POST方法获取到JSON数据时,我们需要对其进行解析。倘若我们使用现有的JSON解析库,这一过程将变得异常简单。在前文中,我们获得了一个翻译结果的JSON数据,具体如下所示
{“sessionUuid”:“translate_uuid1713086664116”,“translate”:{“errCode”:0,“errMsg”:“”,“sessionUuid”:“translate_uuid1713086664116”,“source”:“en”,“target”:“zh”,“records”:[{“sourceText”:“apple”,“targetText”:“苹果”,“traceId”:“523c2dad78254f73afba4a42e618940d”}],“full”:true,“options”:{}},“dict”:null,“suggest”:null,“errCode”:0,“errMsg”:“ok”}
格式化一下方便观看:
{"sessionUuid": "translate_uuid1713086664116","translate": {"errCode": 0,"errMsg": "","sessionUuid": "translate_uuid1713086664116","source": "en","target": "zh","records": [{"sourceText": "apple","targetText": "苹果","traceId": "523c2dad78254f73afba4a42e618940d"}],"full": true,"options": {}},"dict": null,"suggest": null,"errCode": 0,"errMsg": "ok"
}
我们需要提取的是 “targetText”:“苹果”
这段信息。有两种方法可以将其提取出来。一种方法是简单地对字符串进行提取,而另一种方法则是解析JSON数据。当数据内容非常复杂,需要提取许多数组时,我们只能借助解析JSON数据的方法。
方法一:
通过检索 苹果
前后的特定字符串来进行提取。
以下是一个提取字符串的示例函数:
function ExtractBetween(const Source, StartDelimiter, EndDelimiter: string): string;
varStartPos, EndPos: Integer;
beginResult := '';// 查找起始分隔符的位置StartPos := Pos(StartDelimiter, Source);if StartPos > 0 thenbegin// 查找结束分隔符的位置EndPos := Pos(EndDelimiter, Copy(Source, StartPos + Length(StartDelimiter), MaxInt));if EndPos > 0 thenbegin// 调整结束分隔符的位置EndPos := EndPos + StartPos - 1;// 截取中间部分Result := Copy(Source, StartPos + Length(StartDelimiter), EndPos - StartPos);end;end;
end;procedure TForm1.Button1Click(Sender: TObject);
beginMemo2.Text:= ExtractBetween(Memo1.Text, '“targetText”:“', '”,');// 返回 苹果
end;
方法二:
通过JSON解析库来对JSON数据进行解析,我们观察苹果的位置可以看到translate=>records[0]=>targetText
procedure TForm1.Button2Click(Sender: TObject);
varX: ISuperObject;NewJSon: ISuperObject;NewArray: ISuperArray;
beginX := SO(Memo1.Text);Memo2.Text:= X['translate.records[0].targetText'].AsString;
end;
JSON数据已经被成功解析。在此处,我们有必要深入了解JSON的语法以及如何使用JSON解析库来对JSON数据进行全面解析。
一、JSON简介
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。
1、JSON 语法规则
- 数据在名称/值当中
- 数据由逗号分隔
- 大括号 { } 保存对象
- 中括号 [ ] 保存数组,数组可以包含多个对象
- JSON 数据的书写格式是:key : value
- 名称/值对包括字段名称(在双引号中),后面写一个冒号,然后是值:“name” : “名称”
2、JSON值类型
-
数字(整数或浮点数):{ “age”:30 }
-
字符串(在双引号中):{ “name”:“名称” }
-
逻辑值(true 或 false):{ “flag”:true }
-
数组(在中括号中):下面例子中,对象 sites 是包含三个对象的数组。每个对象代表一条关于某个网站(name、url)的记录。
{"sites": [{ "name":"百度" , "url":"www.baidu.com" }, { "name":"google" , "url":"www.google.com" }, { "name":"微博" , "url":"www.weibo.com" }] }
-
对象(在大括号中):上面例子都是对象
-
null:JSON 可以设置 null 值
{ "value":null }
二、JSON解析库使用教程
1、简单生成JSON
假设我们想生成下面的JSON数据
{"name": "Onur YILDIZ", "vip": true,"telephones": ["000000000", "111111111111"],"age": 24,"size": 1.72,"adresses": [{"adress": "blabla","city": "Antalya","pc": 7160},{"adress": "blabla","city": "Adana","pc": 1170}]
}
在Delphi中实现上方JSON对象,我们只需要
procedure TForm1.Button3Click(Sender: TObject);
varX: ISuperObject;// 声明对象
beginX := SO;// X.S[""]表示字符串,注意:虽然json中name两边是双引号但是这里使用单引号X.S['name'] := 'Onur YILDIZ';// X.B[""]表示布尔类型X.B['vip'] := true;// X.A[""]表示数组with X.A['telephones'] dobeginAdd('000000000');Add('111111111111');end;// X.I[""]表示整数X.I['age'] := 24;// X.F[""]表示浮点数X.F['size'] := 1.72;//下面演示了两种添加数组成员的方式with X.A['adresses'].O[0] {Auto Create} do //X.O[""]表示ISuperObject对象beginS['adress'] := 'blabla';S['city'] := 'Antalya';I['pc'] := 7160;end;// orX.A['adresses'].O[1].S['adress'] := 'blabla';X.A['adresses'].O[1].S['city'] := 'Adana';X.A['adresses'].O[1].I['pc'] := 1170;//显示数据,观察生成的JSON数据是否是想要的Memo1.text:= X.AsJSON;
end;
2、简单解析JSON
有下面一段JSON数据(已经做了格式化方便观看),我们需要解析它。
{"o": {"1234567890": {"last use date": "2010-10-17T01:23:20.000","create date": "2010-10-17T01:23:20.000","name": "iPhone 8s"}},"Index": 0,"Data": {"Index2": 1},"a": [{"last use date": "2010-10-17T01:23:20.000","create date": "2010-11-17T01:23:20.000","name": "iPhone 8s","arr": [1,2,3]},{"message": "hello"}]
}
解析JSON代码:
procedure TForm1.Button4Click(Sender: TObject);
constJSON = '{ "o": { '+' "1234567890": {'+' "last use date": "2010-10-17T01:23:20",'+' "create date": "2010-10-17T01:23:20",'+' "name": "iPhone 8s"'+' }'+' },'+' "Index": 0, '+' "Data": {"Index2": 1}, '+' "a": [{'+' "last use date": "2010-10-17T01:23:20",'+' "create date": "2010-11-17T01:23:20",'+' "name": "iPhone 8s",'+' "arr": [1,2,3] '+' }, '+' {'+' message: "hello"'+' }]'+'}';varX: ISuperObject;NewJSon: ISuperObject;NewArray: ISuperArray;
beginX := SO(JSON);ShowMessage( X['o."1234567890"."last use date"'].AsString );ShowMessage( X['a[Index]."create date"'].AsString );ShowMessage( X['a[Data.Index2]."message"'].AsString );X['a[0].arr'].AsArray.Add('test1');// 根据JSON中的数据生成新的NewJSONNewJSON := X['{a: a[Index], b: a[Data.Index2].message, c: o."1234567890".name, d: 4, e: a[0].arr[2], f: " :) "}'].AsObject;NewArray := X['[a[Index], a[Data.Index2].message, Data.Index2, Index, 1, "1", "test"]'].AsArray;
end;
解析只需要根据对象的一层一层嵌套写出解析字符串即可,当然也要注意数组。
像1234567890这种成员是需要在两边加双引号的,不然可能会运行出错。
3、Where 过滤
一个数组中有多个成员,而我们只需要满足特定条件的成员,这里可以使用Where 来做过滤。
procedure TForm1.Button5Click(Sender: TObject);
varFilterJSON: ISuperObject; // 声明一个变量 FilterJSON,类型为 ISuperObject
begin// 使用 SO 函数创建一个 JSON 对象,并将其赋值给 FilterJSON 变量FilterJSON := SO('{ Table: [ ' +' { ' +' Name: "Sakar SHAKIR", ' +' Sex: "M", ' +' Size: 1.75 ' +' }, ' +' { ' +' Name: "Bulent ERSOY", ' +' Sex: "F", ' +' Size: 1.60 ' +' }, ' +' { ' +' Name: "Cicek ABBAS", ' +' Sex: "M", ' +' Size: 1.65 ' +' } ' +' ] ' +'}');// 将筛选后的 JSON 数据添加到 Memo1 控件的行中Memo1.Lines.Add(// 使用 Where 函数筛选 Table 数组中的元素FilterJSON.A['Table'].Where(// 定义一个匿名函数,参数类型为 IMemberfunction(Arg: IMember): Booleanbegin// 获取当前元素的对象表示,并使用 with 块简化代码with Arg.AsObject do// 返回布尔值,判断条件是性别为男性且身高大于1.60米Result := (S['Sex'] = 'M') and (F['Size'] > 1.60)end).AsJSON);
end;
返回:
[
{
“Name”:“Sakar SHAKIR”,
“Sex”:“M”,
“Size”:1.75
},
{
“Name”:“Cicek ABBAS”,
“Sex”:“M”,
“Size”:1.65
} ]
4、Delete 删除
与Where 过滤类似,过滤是根据条件提取出来,删除则是根据条件删掉后再把剩下的成员提取出来,都是对数组成员的筛选
procedure TForm1.Button6Click(Sender: TObject);
varFilterJSON: ISuperObject;
beginFilterJSON := SO('{ Table: [ ' +' { ' +' Name: "Sakar SHAKIR", ' +' Sex: "M", ' +' Size: 1.75 ' +' }, ' +' { ' +' Name: "Bulent ERSOY", ' +' Sex: "F", ' +' Size: 1.60 ' +' }, ' +' { ' +' Name: "Cicek ABBAS", ' +' Sex: "M", ' +' Size: 1.65 ' +' } ' +' ] ' +'}');Memo1.Lines.Add(FilterJSON.A['Table'].Delete(function(Arg: IMember): Booleanbeginwith Arg.AsObject doResult := (S['Sex'] = 'M') and (F['Size'] > 1.60)end).AsJSON);
end;
返回:
[
{
“Name”:“Bulent ERSOY”,
“Sex”:“F”,
“Size”:1.6
} ]
5、Sorting 排序
我们可以根据对象名或者数组中的元素值来排序
procedure TForm1.Button7Click(Sender: TObject);
varX: ISuperObject; // 声明一个变量 X,类型为 ISuperObjectA: ISuperArray; // 声明一个变量 A,类型为 ISuperArray
begin// 使用 SO 函数创建一个 JSON 对象,并将其赋值给变量 XX := SO('{b:1, a:2, d:4, c:2}');// 显示 X 对象的 JSON 表示形式ShowMessage(X.AsJSON);// 对 X 对象进行排序,根据成员的名称进行排序X.Sort(function(Left, Right: IMember): Integerbegin// 使用 CompareText 函数比较成员名称的字典顺序Result := CompareText(Left.Name, Right.Name);end);// 再次显示排序后的 X 对象的 JSON 表示形式ShowMessage(X.AsJSON);// 使用 SA 函数创建一个 JSON 数组,并将其赋值给变量 AA := SA('[{index:3}, {index:4}, {index:2}, {index:1}]');// 显示 A 数组的 JSON 表示形式ShowMessage(A.AsJSON);// 对 A 数组进行排序,根据对象内的 index 属性值进行排序A.Sort(function(Left, Right: IMember): Integerbegin// 使用 CompareValue 函数比较对象内的 index 属性值// CompareValue函数在System.Math单元中Result := CompareValue(Left.AsObject.I['index'], Right.AsObject.I['index']);end);// 再次显示排序后的 A 数组的 JSON 表示形式ShowMessage(A.AsJSON);
end;
返回:
{“b”:1,“a”:2,“d”:4,“c”:2}
{“a”:2,“b”:1,“c”:2,“d”:4}
[{“index”:3},{“index”:4},{“index”:2},{“index”:1}]
[{“index”:1},{“index”:2},{“index”:3},{“index”:4}]
6、Variant 可变类型
可直接对X.V[‘’] 这种直接赋值可变的类型,生成JSON数据的时候可以自动识别赋值的是哪种类型。简直就是懒人必备,特别适合我们。
var X: ISuperObject;
begin X := TSuperObject.Create;X.V['A'] := 1;X.V['B'] := '2';X.V['C'] := 1.3;X.V['D'] := False;X.V['E'] := Null;X.V['F'] := Now;Memo1.Lines.Add(X.AsJSON);
end;
返回:
{
“A”: 1,
“B”: “2”,
“C”: 1.3,
“D”: false,
“E”: null,
“F”: “2014-05-03T03:25:05.059” }
7、Loops 循环遍历
可以对数组的所有成员进行循环遍历。
procedure TForm1.Button9Click(Sender: TObject);
const// 定义一个常量 JSN,存储包含 JSON 数据的字符串JSN = '{ ' +' "adresses": [ ' +' { ' +' "adress": "blabla", ' +' "city": "Antalya", ' +' "pc": 7160 ' +' },' +' { ' +' "adress": "blabla", ' +' "city": "Adana", ' +' "pc": 1170 ' +' } ' +' ] ' +'}';
varX, Obj: ISuperObject; // 声明两个变量 X 和 Obj,类型为 ISuperObjectJ: Integer; // 声明一个整型变量 J
begin// 使用 TSuperObject 类的 Create 方法将 JSON 字符串转换为 SuperObject 对象,并将其赋值给变量 XX := TSuperObject.Create(JSN);// 遍历地址数组with X.A['adresses'] dofor J := 0 to Length - 1 dobegin// 获取当前索引处的地址对象,并赋值给变量 ObjObj := O[J];// 将 Obj 对象的迭代器移动到第一个成员Obj.First;// 遍历 Obj 对象的所有成员while not Obj.EoF dobegin// 将当前成员的键和值输出到 Memo1 控件的一行中Memo1.Lines.Add(Obj.CurrentKey + ' = ' + VarToStr(Obj.CurrentValue.AsVariant));// 将 Obj 对象的迭代器移动到下一个成员Obj.Next;end;Memo1.Lines.Add('------');end;
end;
返回:
adress = blabla
city = Antalya
pc = 7160
adress = blabla
city = Adana
pc = 1170
还有一种枚举遍历的方法,一样的效果。
const// 定义一个常量 JSN,存储包含 JSON 数据的字符串JSN = '{ ' +' "adresses": [ ' +' { ' +' "adress": "blabla", ' +' "city": "Antalya", ' +' "pc": 7160 ' +' },' +' { ' +' "adress": "blabla", ' +' "city": "Adana", ' +' "pc": 1170 ' +' } ' +' ] ' +'}';
varX: ISuperObject;AMember, OMember: IMember;
beginX := TSuperObject.Create(JSN);for AMember in X.A['adresses'] dobeginfor OMember in AMember.AsObject doMemo1.Lines.Add(OMember.Name + ' = ' + OMember.ToString);Memo1.Lines.Add('------');end;
end;
8、JSON与Delphi类互相转换
让JSON数据与类直接关联匹配。
typeTSubClass = classA: Integer;B: Integer;end;TMyClass = classprivateFField: Integer;FSampler: string;FSubClass: TSubClass;publishedproperty field: Integer read FField write FField;property subClass: TSubClass read FSubClass write FSubClass;end;implementationprocedure TForm1.Button11Click(Sender: TObject);
varMyClass: TMyClass;S: string;
beginMemo1.Lines.Clear;//根据json数据直接对MyClass对象赋值MyClass := TMyClass.FromJSON('{"field":12,"subClass":{"A":208,"B":39}}');//测试赋值是否成功if MyClass.field = 12 thenMemo1.Lines.Add('MyClass.field has the correct value of 12');if Assigned(MyClass.subClass) and (MyClass.subClass.A = 208) thenMemo1.Lines.Add('MyClass.subClass.A has the correct value of 208');S := MyClass.AsJSON;Memo1.Lines.Add(S);//通过修改MyClass对象来实现JSON数据的修改if not Assigned(MyClass.subClass) thenMyClass.subClass := TSubClass.Create;MyClass.subClass.A := 345;MyClass.subClass.B := 1024;S := MyClass.AsJSON;Memo1.Lines.Add(S);
end;