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

当我们使用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;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/819346.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

贪心算法先导

贪心算法其实就是没有什么规律可言,所以大家了解贪心算法 就了解它没有规律的本质就够了。 不用花心思去研究其规律, 没有思路就立刻看题解。 基本贪心的题目 有两个极端,要不就是特简单,要不就是死活想不出来。 学完贪心之后再…

算法训练营第41天|LeetCode 343.整数拆分 96.不同的二叉搜索树

LeetCode 343.整数拆分 题目链接: LeetCode 343.整数拆分 解题思路: 递推公式:一个数n是由1到n-1和另一个数的分解而来的,而另一个数是由更小的数分解而来的。 代码: class Solution { public:int integerBreak(…

Springboot+Vue项目-基于Java+MySQL的校园周边美食探索及分享平台系统(附源码+演示视频+LW)

大家好!我是程序猿老A,感谢您阅读本文,欢迎一键三连哦。 💞当前专栏:Java毕业设计 精彩专栏推荐👇🏻👇🏻👇🏻 🎀 Python毕业设计 &…

SU-03T语音识别

语音识别的由SU-03T、咪头、喇叭、还有一个CH340串口组成。SU-03T不需要代码的写入,直接可以进行配置就可以使用,极大降低了开发难度。 为客户提供超低成本的离线语 音识别方案,可广泛且快速应用于智能家居,各类智能小家电&#x…

【BlueDroid】【BLE】开关广播\扫描\配对\连接分析

1. 精讲蓝牙协议栈(Bluetooth Stack):SPP/A2DP/AVRCP/HFP/PBAP/IAP2/HID/MAP/OPP/PAN/GATTC/GATTS/HOGP等协议理论 2. 欢迎大家关注和订阅,【精讲蓝牙协议栈】和【Android Bluetooth Stack】专栏会持续更新中.....敬请期待&#x…

如何实现YOLOv8保存目标检测后的视频文件

首先安装所需的库和依赖项,确保你已经安装了OpenCV和YOLOv8的相关库和依赖项。你可以使用pip或conda来安装它们。 其次加载YOLOv8模型,使用YOLOv8的训练权重文件和配置文件,加载模型并进行初始化。这可以通过使用适当的库函数来完成&…

Java面试题:描述Java 17中的密封接口及其用途

Java 17是继Java 11和Java 16之后的又一个长期支持(LTS)版本,它于2021年9月发布。在Java 17中,一个重要的新特性是密封接口(Sealed Interfaces),这是对Java接口的增强,它允许接口有更…

【Git】Git的安装与常用命令

Git的安装与常用命令 一、Git的安装 (一)下载 官网下载:https://git-scm.com/downloads 镜像网站:https://registry.npmmirror.com/binary.html?pathgit-for-windows/ (二)安装 双击安装&#xff0c…

Elasticsearch分布式搜索

实用篇-ES-环境搭建 ES是elasticsearch的简称。我在SpringBoot学习 数据层解决方案 的时候,写过一次ES笔记,可以结合一起看一下。 之前在SpringBoot里面写的相关ES笔记是基于Windows的,现在我们是基于docker容器来使用,需要你们提…

安装jmeter和ant

安装jmeter和ant 安装java环境 安装jdk和jre 下载Java SE Development Kit 8 Java SE subscribers will receive JDK 8 updates until at least December 2030. 选择指定包进行安装,如windows 共享账号参考:Oracle官网 账号及密码 目前官网下载低…

springboot接口提高查询速度方法

接口想要提高查询速度&#xff0c;需要减少查询数据库的次数&#xff0c;需要把循环里面的查询提出来一次性查询完毕&#xff0c;然后通过java代码来获取响应的值。如下所示&#xff1a; List<OrderInfoHtVO> orderInfoList orderInfoService.getOrderInfoHtlist(query…

K12智慧校园-学工中心

1 系统概述 学工管理系统用于帮助学校学工部门负责拟定学院年度学生工作计划&#xff0c;提出年度学生工作思路及工作要点&#xff0c;并负责指导各系开展学生工作&#xff1b;负责学院的学风建设与校园文明督查&#xff1b;负责新生军训工作的组织、协调和安排&#xff1b;负…

顺序表 (头删 尾删 清空)

//头删 | 1 #include "head.h" | 1 #ifndef ww87 void head_del(p lp) | 2 int main(int argc, const char *argv[]) …

js纯前端实现语音播报,朗读功能(2024-04-15)

实现语音播报要有两个原生API 分别是【window.speechSynthesis】【SpeechSynthesisUtterance】 项目代码 // 执行函数 initVoice({text: 项目介绍,vol: 1,rate: 1 })// 函数 export function initVoice(config) {window.speechSynthesis.cancel();//播报前建议调用取消的函数…

[阅读笔记2][FLAN]FINETUNED LANGUAGE MODELS ARE ZERO-SHOT LEARNERS

接下来这篇是谷歌的FLAN&#xff0c;提出了指令微调这一新范式&#xff0c;在2022年发表。 这篇论文指出GPT3的zero-shot性能相比few-shot性能差太多了。他们发现如果对预训练模型进行指令微调能使zero-shot性能显著提升&#xff0c;下面右图显示指令微调后zero-shot比GPT3 few…

【zml】vp9 vp8

目录 问题 方案 知识点 研究过程 源码编译的可能 问题 所有 的机型 中&#xff0c;就海思芯片的有这个问题。应该是它的h264的编解码 问题&#xff0c;所以目前是让它以vp9在推流就没有问题。 但zlm对于vp9的录相是没有实现的。 所以目前现状是海思芯片的&#xff0c;就…

Ubuntu 22.04安装中文输入法

1. 安装 sudo apt install fcitx5 2. 管理已安装的语言 Setting->Region & Language->Manage Installed Language 在下图中点击“安装”&#xff0c;之后需要等一会 选择Fcitx 5 3. 添加输入法 Setting->Keyboard 点击chinese 选择你想要的输入法 重启一下&a…

安卓选择器

一、首先引入依赖库 //时间选择器implementation io.github.ShawnLin013:number-picker:2.4.13 二、自定义时间选择器 public class TimePickerCustom {private final BottomSheetDialog bottomDialog;private final NumberPicker year;private final NumberPicker month;pr…

【STL】迭代器iterator详解

前言 本篇文章以对string的操作来演示迭代器的操作。 一、什么是迭代器iterator&#xff1f; 迭代器&#xff08;iterator&#xff09;是一种可以遍历容器元素的数据类型。迭代器是一个变量&#xff0c;相当于容器和操纵容器的算法之间的中介。C迭代器是一种用于遍历容器中元的…

pta L1-062 幸运彩票

L1-062 幸运彩票 分数 15 全屏浏览 切换布局 作者 陈越 单位 浙江大学 彩票的号码有 6 位数字&#xff0c;若一张彩票的前 3 位上的数之和等于后 3 位上的数之和&#xff0c;则称这张彩票是幸运的。本题就请你判断给定的彩票是不是幸运的。 输入格式&#xff1a; 输入在第…