首页 前端知识 【Delphi 爬虫库 2】使用封装好的 JSON 解析库对 JSON 数据进行解析

【Delphi 爬虫库 2】使用封装好的 JSON 解析库对 JSON 数据进行解析

2024-06-26 23:06:07 前端知识 前端哥 727 738 我要收藏

当我们使用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;
转载请注明出处或者链接地址:https://www.qianduange.cn//article/13629.html
标签
爬虫
评论
发布的文章

JQuery中的load()、$

2024-05-10 08:05:15

大家推荐的文章
会员中心 联系我 留言建议 回顶部
复制成功!