当我们使用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;
var
StartPos, EndPos: Integer;
begin
Result := '';
// 查找起始分隔符的位置
StartPos := Pos(StartDelimiter, Source);
if StartPos > 0 then
begin
// 查找结束分隔符的位置
EndPos := Pos(EndDelimiter, Copy(Source, StartPos + Length(StartDelimiter), MaxInt));
if EndPos > 0 then
begin
// 调整结束分隔符的位置
EndPos := EndPos + StartPos - 1;
// 截取中间部分
Result := Copy(Source, StartPos + Length(StartDelimiter), EndPos - StartPos);
end;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
Memo2.Text:= ExtractBetween(Memo1.Text, '“targetText”:“', '”,');// 返回 苹果
end;
方法二:
通过JSON解析库来对JSON数据进行解析,我们观察苹果的位置可以看到translate=>records[0]=>targetText
procedure TForm1.Button2Click(Sender: TObject);
var
X: ISuperObject;
NewJSon: ISuperObject;
NewArray: ISuperArray;
begin
X := 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);
var
X: ISuperObject;// 声明对象
begin
X := SO;
// X.S[""]表示字符串,注意:虽然json中name两边是双引号但是这里使用单引号
X.S['name'] := 'Onur YILDIZ';
// X.B[""]表示布尔类型
X.B['vip'] := true;
// X.A[""]表示数组
with X.A['telephones'] do
begin
Add('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对象
begin
S['adress'] := 'blabla';
S['city'] := 'Antalya';
I['pc'] := 7160;
end;
// or
X.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);
const
JSON = '{ "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"'+
' }]'+
'}';
var
X: ISuperObject;
NewJSon: ISuperObject;
NewArray: ISuperArray;
begin
X := 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中的数据生成新的NewJSON
NewJSON := 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);
var
FilterJSON: 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(
// 定义一个匿名函数,参数类型为 IMember
function(Arg: IMember): Boolean
begin
// 获取当前元素的对象表示,并使用 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);
var
FilterJSON: ISuperObject;
begin
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 ' +
' } ' +
' ] ' +
'}');
Memo1.Lines.Add(
FilterJSON.A['Table'].Delete(
function(Arg: IMember): Boolean
begin
with Arg.AsObject do
Result := (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);
var
X: ISuperObject; // 声明一个变量 X,类型为 ISuperObject
A: ISuperArray; // 声明一个变量 A,类型为 ISuperArray
begin
// 使用 SO 函数创建一个 JSON 对象,并将其赋值给变量 X
X := SO('{b:1, a:2, d:4, c:2}');
// 显示 X 对象的 JSON 表示形式
ShowMessage(X.AsJSON);
// 对 X 对象进行排序,根据成员的名称进行排序
X.Sort(
function(Left, Right: IMember): Integer
begin
// 使用 CompareText 函数比较成员名称的字典顺序
Result := CompareText(Left.Name, Right.Name);
end);
// 再次显示排序后的 X 对象的 JSON 表示形式
ShowMessage(X.AsJSON);
// 使用 SA 函数创建一个 JSON 数组,并将其赋值给变量 A
A := SA('[{index:3}, {index:4}, {index:2}, {index:1}]');
// 显示 A 数组的 JSON 表示形式
ShowMessage(A.AsJSON);
// 对 A 数组进行排序,根据对象内的 index 属性值进行排序
A.Sort(
function(Left, Right: IMember): Integer
begin
// 使用 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 ' +
' } ' +
' ] ' +
'}';
var
X, Obj: ISuperObject; // 声明两个变量 X 和 Obj,类型为 ISuperObject
J: Integer; // 声明一个整型变量 J
begin
// 使用 TSuperObject 类的 Create 方法将 JSON 字符串转换为 SuperObject 对象,并将其赋值给变量 X
X := TSuperObject.Create(JSN);
// 遍历地址数组
with X.A['adresses'] do
for J := 0 to Length - 1 do
begin
// 获取当前索引处的地址对象,并赋值给变量 Obj
Obj := O[J];
// 将 Obj 对象的迭代器移动到第一个成员
Obj.First;
// 遍历 Obj 对象的所有成员
while not Obj.EoF do
begin
// 将当前成员的键和值输出到 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 ' +
' } ' +
' ] ' +
'}';
var
X: ISuperObject;
AMember, OMember: IMember;
begin
X := TSuperObject.Create(JSN);
for AMember in X.A['adresses'] do
begin
for OMember in AMember.AsObject do
Memo1.Lines.Add(OMember.Name + ' = ' + OMember.ToString);
Memo1.Lines.Add('------');
end;
end;
8、JSON与Delphi类互相转换
让JSON数据与类直接关联匹配。
type
TSubClass = class
A: Integer;
B: Integer;
end;
TMyClass = class
private
FField: Integer;
FSampler: string;
FSubClass: TSubClass;
published
property field: Integer read FField write FField;
property subClass: TSubClass read FSubClass write FSubClass;
end;
implementation
procedure TForm1.Button11Click(Sender: TObject);
var
MyClass: TMyClass;
S: string;
begin
Memo1.Lines.Clear;
//根据json数据直接对MyClass对象赋值
MyClass := TMyClass.FromJSON('{"field":12,"subClass":{"A":208,"B":39}}');
//测试赋值是否成功
if MyClass.field = 12 then
Memo1.Lines.Add('MyClass.field has the correct value of 12');
if Assigned(MyClass.subClass) and (MyClass.subClass.A = 208) then
Memo1.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) then
MyClass.subClass := TSubClass.Create;
MyClass.subClass.A := 345;
MyClass.subClass.B := 1024;
S := MyClass.AsJSON;
Memo1.Lines.Add(S);
end;