mormot2生成JSON和解析JSON的功能非常强大,也非常灵活,灵活的结果就是有时候有点乱。下面总结了最简单的一种使用方法
要解析的JSON如下,基本涉及了要解析的所有类型。
JsonContent:='
{
"head": {
"jzDate": "2023-08-22",
"saleNo": "2023081770711821",
"ssTotal": -98.00,
"xsDate": "2023-08-17 15:03:01",
},
"pay": [
{
"saleNo": "2023081770711821",
"ssTotal": -98.00,
"zfCode": "9410",
"zfName": "电商",
"zfTotal": -98.00
}
],
"salePlu": [
{
"barCode": "2000830153165",
"pluID": 80020000276608,
"pluName": "百威七星伴月月饼礼盒",
"price": 98.0000,
"saleNO": "2023081770711821",
"spec": "880g",
"ssTotal": -98.00,
"unit": "盒",
"xsCount": -1,
"xsDate": "2023-08-17 15:03:01",
}
]
}
';
首先引用单元mormot.core.variants, mormot.core.text,mormot.core.base, mormot.core.json
var
JsonData:Variant;
BillHead:Variant;
SaleNO:string;
PluArray:Variant;
PluItem:Variant;
I:integer;
pluID:Int64;
pluName,PluUnit:string;
Price:double;
begin
JsonData:= _Json(JsonContent); //将JSON字符串转换为Json的对象 VariantSaveJSON(JSONValue)可以将
//Variant对象直接转成JSON字符串
//JsonParam.Exists('head'); //判断节点是否存在
//JsonParam.head.Exists('saleNo')//直接判断子节点是否存在
BillHead:= JsonData.head;
SaleNO:=BillHead.saleNo; //直接取值即可,如果不存在会报异常
PluArray:=JsonData.salePlu; //还是直接取
for I:=0 to PluArray._Count-1 do
begin
PluItem:=_Safe(PluList)^.Value[I];
pluID:=PluItem.pluID;
pluName:=PluItem.pluName;
Price:=PluItem.price;
PluUnit:=_Safe(PluItem)^.S['unit']; //个别Json节点名与系统关键字冲突的可以改为这种方式
end;
end;
其它场景
var
Order: Variant;
PluList: Variant;
PluItem: Variant;
begin
TDocVariant.New(Order);
Order.entId := 0; //企业ID
Order.posId := '20230910225580001'; //POSID
//初始化商品信息
TDocVariant.New(PluItem);
PluItem.rowNo := 1; //销售商品行号
PluItem.pluCode := '100038'; //商品编码
//将商品信息增加到JSONArray中
TDocVariantData(PluList).AddItem(PluItem) ;
Order.pluList:=PluList;
end;
// !var
// ! Doc: TDocVariantData; // stack-allocated variable
// !begin
// ! Doc.Init;
// ! Doc.AddValue('name','John');
// ! assert(Doc.Value['name']='John');
// ! assert(variant(Doc).name='John');
// !end;
// ! var v: PVariant;
// ! ...
// ! dv.InitArray([1, 3, 3, 4]);
// ! for v in dv.Items do
// ! writeln(v^);
// ! // output 1 2 3 4
// ! var d: PDocVariantData;
// ! ...
// ! dv.InitJson('[{a:1,b:1},1,"no object",{a:2,b:2}]');
// ! for d in dv.Objects do
// ! writeln(d^.ToJson);
// ! // output {"a":1,"b":1} and {"a":2,"b":2} only
// ! // (ignoring 1 and "no object" items)
// ! var Doc: TDocVariantData;
// ! i: integer;
// !begin
// ! Doc.Init;
// ! Doc.AddItem('one');
// ! Doc.AddItem(2);
// ! Doc.AddItem(3.0);
// ! assert(Doc.Count=3);
// ! for i := 0 to Doc.Count-1 do
// ! writeln(Doc.Value[i]);
// !Doc.InitObject(['name','John','year',1972]);
// which is the same as:
// ! var Doc: TDocVariantData;
// !begin
// ! Doc.Init;
// ! Doc.AddValue('name','John');
// ! Doc.AddValue('year',1972);
// !end;
最近看官方文档,发现一种新的解析方法感觉非常简单,示例代码如下:
var
list: IDocList;
dict: IDocDict;
v: variant;
i: integer;
begin
// creating a new list/array from items
list := DocList([1, 2, 3, 'four', 1.0594631]); // double are allowed by default
// iterating over the list
for v in list do
Listbox1.Items.Add(v); // convert from variant to string
// or a sub-range of the list (with Python-like negative indexes)
for i in list.Range(0, -3) do
Listbox2.Items.Add(IntToStr(i)); // [1, 2] as integer
// search for the existence of some elements
assert(list.Exists(2));
assert(list.Exists('four'));
// a list of objects, from JSON, with an intruder
list := DocList('[{"a":0,"b":20},{"a":1,"b":21},"to be ignored",{"a":2,"b":22}]');
// enumerate all objects/dictionaries, ignoring non-objects elements
for dict in list.Objects do
begin
if dict.Exists('b') then
ListBox2.Items.Add(dict['b']);
if dict.Get('a', i) then
ListBox3.Items.Add(IntToStr(i));
end;
// delete one element
list.Del(1);
assert(list.Json = '[{"a":0,"b":20},"to be ignored",{"a":2,"b":22}]');
// extract one element
if list.PopItem(v, 1) then
assert(v = 'to be ignored');
// convert to a JSON string
Label1.Caption := list.ToString;
// display '[{"a":0,"b":20},{"a":2,"b":22}]'
end;
并且支持高级的特性,比如条件过滤
var
v: variant;
f: TDocDictFields;
list, list2: IDocList;
dict: IDocDict;
begin
list := DocList('[{"a":10,"b":20},{"a":1,"b":21},{"a":11,"b":20}]');
// sort a list/array by the nested objects field(s)
list.SortByKeyValue(['b', 'a']);
assert(list.Json = '[{"a":10,"b":20},{"a":11,"b":20},{"a":1,"b":21}]');
// enumerate a list/array with a conditional expression :)
for dict in list.Objects('b<21') do
assert(dict.I['b'] < 21);
// another enumeration with a variable as conditional expression
for dict in list.Objects('a=', 10) do
assert(dict.I['a'] = 10);
// create a new IDocList from a conditional expression
list2 := list.Filter('b =', 20);
assert(list2.Json = '[{"a":10,"b":20},{"a":11,"b":20}]');
// direct access to the internal TDocVariantData storage
assert(list.Value^.Count = 3);
assert(list.Value^.Kind = dvArray);
assert(dict.Value^.Kind = dvObject);
// TDocVariantData from a variant intermediary
v := list.AsVariant;
assert(_Safe(v)^.Count = 3);
v := dict.AsVariant;
assert(_Safe(v)^.Count = 2);
// high-level Python-like methods
if list.Len > 0 then
while list.PopItem(v) do
begin
assert(list.Count(v) = 0); // count the number of appearances
assert(not list.Exists(v));
Listbox1.Items.Add(v.a); // late binding
dict := DocDictFrom(v); // transtyping from variant to IDocDict
assert(dict.Exists('a') and dict.Exists('b'));
// enumerate the key:value elements of this dictionary
for f in dict do
begin
Listbox2.Items.Add(f.Key);
Listbox3.Items.Add(f.Value);
end;
end;
// create from any complex "compact" JSON
// (note the key names are not "quoted")
list := DocList('[{ab:1,cd:{ef:"two"}}]');
// we still have the late binding magic working
assert(list[0].ab = 1);
assert(list[0].cd.ef = 'two');
// create a dictionary from key:value pairs supplied from code
dict := DocDict(['one', 1, 'two', 2, 'three', _Arr([5, 6, 7, 'huit'])]);
assert(dict.Len = 3); // one dictionary with 3 elements
assert(dict.Json = '{"one":1,"two":2,"three":[5,6,7,"huit"]}');
// convert to JSON with nice formatting (line feeds and spaces)
Memo1.Caption := dic.ToString(jsonHumanReadable);
// sort by key names
dict.Sort;
assert(dict.Json = '{"one":1,"three":[5,6,7,"huit"],"two":2}');
// note that it will ensure faster O(log(n)) key lookup after Sort:
// (beneficial for performance on objects with a high number of keys)
assert(dict['two'] = 2); // default lookup as variant value
assert(dict.I['two'] = 2); // explicit conversion to integer
end;
真是越来越高级了。
注意:将函数内IDocDict的部分对象IDocDict或者IDocList返回到函数外部时,使用其Copy方法复制后返回,不然会因为其主体在函数执行完后被销毁而变成null
示例参考自官方文章
https://blog.synopse.info/?post/2024/02/01/Easy-JSON-with-Delphi-and-FPC
还不快抢沙发