mORMot2 生成和解析 JSON

这篇具有很好参考价值的文章主要介绍了mORMot2 生成和解析 JSON。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

mormot2 生成和解析json

本文非完全原创,本文部分内容来自博客园,作者:{咏南中间件}

前综合示例,整个示例是建立在mORMot特有的实现模式的基础上,非常用的序列化反序列化,但又有别于字符串拼接,据说效率极高。

unit Unit1;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls,
  Forms, Dialogs, StdCtrls,
  mormot.core.perf,
  mormot.core.Data,
  mormot.core.text,
  mormot.core.json,
  mormot.core.variants,
  mormot.core.base,
  mormot.core.log ;
 
type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
 
var
  Form1: TForm1;
 
implementation
 
{$R *.dfm}

解析JSON:

  • 基础

下面是最基本的方法,如何定位!这里用到了 GetValueByPath 函数。

procedure TForm1.Button1Click(Sender: TObject);
//解析json
var
  js: TDocVariantData;//这个类型就是mormot利用Variant扩展的特有方案
  json: string;
begin
  json := '{"tt":"1"}';
  js.InitJSON(json); //从字符串到Variant
  Caption := js.GetValueByPath(['tt']);//定位
end;
  • 进阶

通过 DocVariantData(GetValueByPath (xxx)).Value[ ] 可以访问对于Array或者List可以访问元素值

对于 TDocVariantData类型的变量可以通过特征属性函数直接访问【U[]:RawUtf8;S[]:string;B[]:boolean;I[]:Int64;D[]:double;O[]:PDocVariantData;O_[] A[]:PDocVariantData; A_[] _[]】

(*
{
  "blockCount":3,
  "blocks":[
    {"FieldCount":1, "fields":[{"Name":"姓名", "Value":["张1", "张2","张三"]}]},
    {"FieldCount":1, "fields":[{"Name":"单位", "Value":["华2", "张2","张三"]}]},
    {"FieldCount":1, "fields":[{"Name":"单位", "Value":["华拓", "张2","张三"]}]}
  ]
}
*)
 
procedure TForm1.Button2Click(Sender: TObject);
//解析json
var
  js, js2, js3: TDocVariantData;
begin
  js.InitJSONFromFile('tt.json');
  caption := DocVariantData(js.GetValueByPath(['blocks'])).value[0]; //{"FieldCount":1, "fields":[{"Name":"姓名", "Value":["张1", "张2","张三"]}]}
  js2.InitJSON(caption);
  caption := DocVariantData(js2.GetValueByPath(['fields'])).value[0]; //{"Name":"姓名", "Value":["张1", "张2","张三"]}
  js3.InitJSON(caption);
  Caption := js3.U['Name'] + DocVariantData(js3.GetValueByPath(['Value'])).value[0]; //姓名张1
  caption := DocVariantData(DocVariantData(js.A['blocks'].Value[1]).A['fields'].Value[0]).A['Value'].Value[0]; //华2
end;

生成JSON:

(*
{"Name":"Str0","Age":0,"List":[1,"Hello",5,{"name":"咏南中间件","age":99}]}
{"Name":"Str1","Age":1,"List":[1,"Hello",5,{"name":"咏南中间件","age":99}]}
*)
procedure TForm1.Button3Click(Sender: TObject);
//生成json
var
  jo: Variant;
  i: Int64;
begin
  TDocVariant.New(jo);
  i := 0;
  while i < 2 do
  begin
    jo.Name := 'Str' + IntToStr(i);
    jo.Age := i;
    jo.List := _JSon('[1,"Hello",5,{"name":"咏南中间件","age":99}]');
    Memo1.Lines.Add(VariantSaveJSON(jo));
    inc(i);
  end;
end;
 
end.

关于TDocVariantData:

利用TDocVariantData做json解析, 就是在这个文档(JSON文档,文档泛指JSON)中查找一个项目,并返回其值。

  • 如果aNameOrIndex既不是整数也不是字符串,则抛出EDocVariant异常
  • 如果Kind是dvArray且aNameOrIndex是字符串,或者Kind是dvObject且aNameOrIndex是整数,则抛出EDocVariant异常
  • 如果Kind是dvObject且aNameOrIndex是字符串,在对象属性名称中找不到该字符串,且Options中设置了dvoReturnNullForUnknownProperty,则抛出EDocVariant异常
  • 如果Kind是dvArray且aNameOrIndex是整数,该整数不在0到Count-1的范围内,且Options中设置了dvoReturnNullForUnknownProperty,则抛出EDocVariant异常
  • 因此,您可以直接这样使用:

对于数组类型的文档:

aVariant := TDocVariant.NewArray(['one',2,3.0]);
for i := 0 to TDocVariantData(aVariant).Count-1 do
  aValue := TDocVariantData(aVariant).Value[i];

对于对象类型的文档:

aVariant := TDocVariant.NewObject(['name','John','year',1972]);
assert(aVariant.Name=TDocVariantData(aVariant)['name']);
assert(aVariant.year=TDocVariantData(aVariant)['year']);

由于变体的执行内部实现(较慢的_DispInvoke()函数),执行以下操作会稍快一些:

aValue := TDocVariantData(aVariant).Value['name'];
// 或者
aValue := _Safe(aVariant).Value['name'];

// 而不是
aValue := aVariant.name;

当然,如果想通过索引访问内容(通常是dvArray),使用Values[]和Names[]属性会比使用变体索引的伪属性更快:

with TDocVariantData(aVariant) do
for i := 0 to Count-1 do
Writeln(Values[i]); //这里是Values

比以下代码更快:

with TDocVariantData(aVariant) do
  for i := 0 to Count-1 do
  Writeln(Value[i]);

这又比以下代码更快:

for i := 0 to aVariant.Count-1 do
Writeln(aVariant._(i));

此属性将值作为varByRef返回(就像对任何TDocVariant实例的变体后期绑定一样),因此您可以这样写:

var
  Doc: TDocVariantData; // 栈上分配的变量
begin
  Doc.InitJson('{arr:[1,3]}');
  assert(Doc.Count=2);
  Doc.Value['arr'].Add(7); // 由于Doc.Value['arr']是varByRef,因此可以工作
  writeln(Doc.ToJson); // 将输出 '{"arr":[1,3,7]}'
end;

关于TDocVariant:

当然,以下是对注释区域的翻译,同时我使用 Markdown 语法来高亮代码,并去掉了行注释标志:


这是一个自定义的变体类型,用于存储任何基于JSON/BSON文档的内容。

  • 即,对象的名字/值对,或者值数组(包括嵌套文档),这些都被存储在 TDocVariantData内存结构中。
  • 你可以使用 _Obj()/_ObjFast(), _Arr()/_ArrFast(), _Json()/_JsonFast(), 或者 _JsonFmt()/_JsonFastFmt()函数来创建这种变体的实例。
  • 属性访问可以通过后期绑定来实现 - 对于较旧版本的FPC有一些限制,例如允许编写:
TDocVariant.NewFast(aVariant);

aVariant.Name := 'John';

aVariant.Age := 35;

writeln(aVariant.Name, ' is ', aVariant.Age, ' years old');
  • 它还支持一小套伪属性或伪方法:
aVariant._Count // 等同于 DocVariantData(aVariant).Count,访问元素数量

aVariant._Kind  // 等同于 ord(DocVariantData(aVariant).Kind),访问变体的类型(以整数的形式)

aVariant._JSON  // 等同于 DocVariantData(aVariant).JSON,访问变体的JSON表示

aVariant._(i)   // 等同于 DocVariantData(aVariant).Value[i],使用索引访问元素的值

aVariant.Value(i)   // 另一种通过索引访问值的方式,更明确

aVariant.Value(aName) // 等同于 DocVariantData(aVariant).Value[aName],使用名字访问元素的值

aVariant.Name(i) // 等同于 DocVariantData(aVariant).Name[i],访问元素的名字

aVariant.Add(aItem) // 等同于 DocVariantData(aVariant).AddItem(aItem),向变体中添加一个元素

aVariant._ := aItem // 另一种添加元素的方式,语法更简洁

aVariant.Add(aName, aValue) // 等同于 DocVariantData(aVariant).AddValue(aName, aValue),向变体中添加一个命名值对

aVariant.Exists(aName) // 等同于 DocVariantData(aVariant).GetValueIndex(aName)>=0,检查一个名字是否存在于变体中

aVariant.Delete(i) // 等同于 DocVariantData(aVariant).Delete(i),通过索引删除一个元素

aVariant.Delete(aName) // 等同于 DocVariantData(aVariant).Delete(aName),通过名字删除一个元素

aVariant.NameIndex(aName) // 等同于 DocVariantData(aVariant).GetValueIndex(aName),通过名字获取元素的索引
  • 它具有直接的JSON序列化/反序列化功能,例如:
assert(_Json('["one",2,3]')._JSON = '["one",2,3]');
  • 它具有将字符串直接转码为JSON编码字符串的功能,例如:
assert(_Json('["one",2,3]') = '["one",2,3]');

后综合示例

弄明白mORMot的JSON,实际就是变体类型应用,他的快在于Variant本身,同时也受限于Variant有上限,估计通过优化提升不了太多。

这是一个用于存储基于JSON/BSON文档的内容的自定义变体类型。

功能特性:

  • 存储对象的名字/值对或值数组(可嵌套)。
  • 通过特定的创建函数实例化。
  • 支持后期绑定的属性访问。
  • 提供一系列伪属性和伪方法进行操作。
  • 允许直接的JSON序列化和反序列化。

示例代码和注释:

// 创建一个新的变体实例
var aVariant: TDocVariant;
TDocVariant.NewFast(aVariant);

// 设置和获取属性
aVariant.Name := 'John'; // 设置名字属性
aVariant.Age := 35;     // 设置年龄属性
writeln(aVariant.Name, ' is ', aVariant.Age, ' years old'); // 输出属性

// 访问伪属性和伪方法
writeln('Count: ', aVariant._Count);        // 元素数量
writeln('Kind: ', aVariant._Kind);          // 变体类型(整数形式)
writeln('JSON: ', aVariant._JSON);          // 变体的JSON表示
writeln('Value at index 1: ', aVariant._(1)); // 通过索引访问元素值

// 添加元素和值
aVariant.Add('City');                      // 添加一个元素
aVariant.Add('Country', 'USA');             // 添加一个命名值对

// 检查元素是否存在并删除
if aVariant.Exists('Country') then
  writeln('Country exists.');
aVariant.Delete('Country');                // 通过名字删除元素

// JSON序列化和反序列化示例
var jsonString: string;
jsonString := aVariant._JSON;               // 序列化为JSON字符串
// ... 此处可以保存或传输 jsonString ...
aVariant := _Json(jsonString);             // 从JSON字符串反序列化

// 验证JSON字符串直接转码功能
assert(_Json('["one",2,3]') = '["one",2,3]');

注意:文章来源地址https://www.toymoban.com/news/detail-857688.html

  • 实际使用时,TDocVariant 类型和相关方法需要根据您的具体实现或第三方库进行定义和实现。
  • 伪属性和伪方法的实现取决于底层 DocVariantData结构的具体实现细节。
  • 序列化、反序列化和转码功能可能依赖于外部库或自定义实现。

到了这里,关于mORMot2 生成和解析 JSON的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 二维码生成解析用ZXing.NET就够了,不要再引一堆生成和解析库了

    ZXing.NET 是一个开源的、功能强大的二维码处理库,它能够对二维码进行解码(读取信息)和编码(生成二维码)。ZXing 是 \\\"Zebra Crossing\\\" 的缩写,是一个跨平台的、用于解码和生成条形码和二维码的库。以下是一些 ZXing.Net 的主要功能通过实例讲解。 这些示例演示了 ZXing.Net 的

    2024年02月04日
    浏览(43)
  • 【算法】列生成算法原理解析

    列生成算法是一种算法框架(也可以称为是一种思想,不能单独用来具体求解),运用DW分解将问题分解为主问题和子问题,在子问题中求出检验数最优的列(子问题的求解需要用其他诸如启发式、求解器等进行求解),将此列加入主问题中进行求解(主问题求解方式可以是

    2024年02月05日
    浏览(35)
  • Java 解析 /生成 Excel文件

    目录 一.概述 二.Apache POI 1.XSSF解析文件 2.XSSF生成文件 三.Alibaba EasyExcel 四.SXSSF写入文件         在程序的开发过程中,通常会使用Excel文件来进行数据的导入和导出,在使用Java实现此类需求时也要经理Excel文件的解析或生成         在Java技术中,能实现此类需求的技术

    2024年01月20日
    浏览(39)
  • Hyperledger Fabric 生成组织身份解析

    fabric 版本 2.4.1 Fabric 网络通过证书和密钥来管理和认证成员身份,经常需要生成证书文件。通常这些操作可以使用 PKI 服务(如 Fabric-CA)或者 OpenSSL 工具来实现(针对单个证书的签发)。为了方便批量管理组织证书,Fabric 基于 Go 语言的标准 crypto 库提供了 cryptogen (crypto ge

    2024年01月22日
    浏览(30)
  • Qt_生成和解析二维码

    项目介绍: 在使用qt的时候突发奇想,二维码是怎么生成的呢? 通过网上查找资料终于解决了这个问题。 原理 其实二维码的生成和解析都有已经写好的库,这个库用起来也特别简单。 下面是相关内容。 相关库: qrcode:https://fukuchi.org/works/qrencode/ QZXing:https://github.com/ruise

    2024年02月12日
    浏览(39)
  • JSON Schema&表单UI快速生成解析

    ​ JSON(JavaScript Object Notation)是一种轻量常见的数据交换格式,基本的数据的结构就是key-value,具有易于生成和解析的优点,通过JSON可以灵活地表达程序所需要的数据结构。 ​ 但JSON本身并没有特定的规范(本身结构也不支持注释),所以对于数据本身的描述是缺失的,比

    2023年04月08日
    浏览(33)
  • Shell工具脚本-生成文件&下载资源并解析

    主要包含功能如下: 1.自动生成文件 2.下载文件并解析 #  @Author: lvzhihong #  @Date: 2023-08-29 08:43:41 #! /bin/bash #config project_code=(\\\"23861\\\"  \\\"23862\\\" \\\"23863\\\") project_out_root=\\\"aon_project_output\\\" project_apk_url=\\\"xxx/2023082904130232_APP_INFO_repo_10010111.xml\\\"; declare -A aon_module_feature_map aon_module_feature_map[\\\"gaze\\\"]=\\\"

    2024年02月11日
    浏览(39)
  • 什么是Java中的JSON解析和生成?

    首先,我们来解释一下JSON是什么。简单来说,JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于阅读和编写,同时也易于解析和生成。在Java中,我们有很多种方式来实现JSON解析和生成。接下来,我们来看一下代码示例吧! 首先,我们来看一下JSON解析。假设我

    2024年02月15日
    浏览(43)
  • C# QRCode二维码的解析与生成

    已知一张二维码图片,怎么生成一张一模一样的图片出来? 最近有个项目,需要用到QRCode,之前只做过Datamatrix格式的,想着应该也是差不多的,于是就依葫芦画瓢,掏出我的陈年OnBarcode类库,一通修改,生成了个崭新的QRCode,与客户提供的二维码图片一比对,虽然扫出来内

    2024年02月12日
    浏览(54)
  • js生成二维码和解析二维码

    这个整了好久,用的包换了好几次,所以记录一下 生成二维码 解析二维码 然后是两个引入的js reqrcode和qrcode

    2023年04月09日
    浏览(52)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包