REST easy with kbmMW #24 使用kbmMW实现JSON/XML/YAML转换成对象

时间:2023-03-09 16:14:09
REST easy with kbmMW #24 使用kbmMW实现JSON/XML/YAML转换成对象

你想过没有,把一个给定的xml或json生成一个Delphi类,并通过这个类完成对xml或json的读写操作吗?

不管有没有,现在kbmMW为我们实现了,看下面这行代码:

var
s:string;
...
s:=TkbmMWJSONMarshal.GenerateDelphiClassFromUTF8File('auctions.json','Unit2','JSONData');
...
{
"realm":{"name":"Aegwynn","slug":"aegwynn"},
"alliance":{"auctions":[
{"auc":1972333274,"item":22574,"owner":"Schäuble","bid":51300,"buyout":54000,"quantity":1,"timeLeft":"VERY_LONG","rand":0,"seed":30355200},
{"auc":1970925966,"item":22446,"owner":"Aenni","bid":1890000,"buyout":2450000,"quantity":10,"timeLeft":"LONG","rand":0,"seed":1280052352},
{"auc":1972187088,"item":82800,"owner":"Ainshu","bid":4329000,"buyout":4329000,"quantity":1,"timeLeft":"VERY_LONG","rand":0,"seed":955897088,"petSpeciesId":122,"petBreedId":5,"petLevel":1,"petQualityId":2},
{"auc":1972201216,"item":51950,"owner":"Ulath","bid":119157,"buyout":121590,"quantity":3,"timeLeft":"VERY_LONG","rand":0,"seed":1109650432},
... + entries
]},
"horde":{"auctions":[
{"auc":1970970808,"item":82952,"owner":"Guldarak","bid":4004290,"buyout":4004426,"quantity":1,"timeLeft":"LONG","rand":0,"seed":950078272},
{"auc":1971973942,"item":4306,"owner":"Blutrabé","bid":94500,"buyout":99999,"quantity":20,"timeLeft":"VERY_LONG","rand":0,"seed":956528896},
{"auc":1971973992,"item":4306,"owner":"Blutrabé","bid":94500,"buyout":99999,"quantity":20,"timeLeft":"VERY_LONG","rand":0,"seed":1476867968},
{"auc":1972449149,"item":87893,"owner":"Thêlon","bid":2375000,"buyout":2500000,"quantity":1,"timeLeft":"VERY_LONG","rand":0,"seed":848616448},
{"auc":1971763986,"item":74705,"owner":"Gondoline","bid":15558129,"buyout":16662661,"quantity":1,"timeLeft":"LONG","rand":0,"seed":577727872},
... + entries
]},
"neutral":{"auctions":[
{"auc":1971600068,"item":72145,"owner":"Mellkore","bid":59990000,"buyout":59990000,"quantity":1,"timeLeft":"VERY_LONG","rand":0,"seed":436886144},
{"auc":1972336265,"item":8485,"owner":"Zaruman","bid":351500,"buyout":450000,"quantity":1,"timeLeft":"VERY_LONG","rand":0,"seed":0},
{"auc":1972336316,"item":8487,"owner":"Zaruman","bid":351500,"buyout":450000,"quantity":1,"timeLeft":"VERY_LONG","rand":0,"seed":0},
{"auc":1972336611,"item":8487,"owner":"Zaruman","bid":351500,"buyout":450000,"quantity":1,"timeLeft":"VERY_LONG","rand":0,"seed":0},
{"auc":1972336922,"item":8488,"owner":"Zaruman","bid":351500,"buyout":450000,"quantity":1,"timeLeft":"VERY_LONG","rand":0,"seed":0},
{"auc":1972336986,"item":8488,"owner":"Zaruman","bid":351500,"buyout":450000,"quantity":1,"timeLeft":"VERY_LONG","rand":0,"seed":0},
{"auc":1971335148,"item":76085,"owner":"Splatthy","bid":4418750,"buyout":4950000,"quantity":5,"timeLeft":"VERY_LONG","rand":0,"seed":2058173312},
{"auc":1972336837,"item":8487,"owner":"Zaruman","bid":351500,"buyout":450000,"quantity":1,"timeLeft":"VERY_LONG","rand":0,"seed":0},
{"auc":1972336524,"item":8486,"owner":"Zaruman","bid":351500,"buyout":450000,"quantity":1,"timeLeft":"VERY_LONG","rand":0,"seed":0},
{"auc":1971335152,"item":76085,"owner":"Splatthy","bid":4418750,"buyout":4950000,"quantity":5,"timeLeft":"VERY_LONG","rand":0,"seed":2058173312},
{"auc":1972336351,"item":8485,"owner":"Zaruman","bid":351500,"buyout":450000,"quantity":1,"timeLeft":"VERY_LONG","rand":0,"seed":0},
{"auc":1972386885,"item":4338,"owner":"Huntez","bid":90284,"buyout":95038,"quantity":15,"timeLeft":"VERY_LONG","rand":0,"seed":944449152},
{"auc":1971335163,"item":76085,"owner":"Splatthy","bid":17675000,"buyout":19800000,"quantity":20,"timeLeft":"VERY_LONG","rand":0,"seed":1033557888},
{"auc":1972336774,"item":8487,"owner":"Zaruman","bid":351500,"buyout":450000,"quantity":1,"timeLeft":"VERY_LONG","rand":0,"seed":0},
{"auc":1971335155,"item":76085,"owner":"Splatthy","bid":4418750,"buyout":4950000,"quantity":5,"timeLeft":"VERY_LONG","rand":0,"seed":2058173312},
{"auc":1972336383,"item":8485,"owner":"Zaruman","bid":351500,"buyout":450000,"quantity":1,"timeLeft":"VERY_LONG","rand":0,"seed":0},
{"auc":1972336563,"item":8486,"owner":"Zaruman","bid":351500,"buyout":450000,"quantity":1,"timeLeft":"VERY_LONG","rand":0,"seed":0},
{"auc":1972386607,"item":12808,"owner":"Huntez","bid":71499,"buyout":79999,"quantity":1,"timeLeft":"VERY_LONG","rand":0,"seed":266490112},
{"auc":1971335149,"item":76085,"owner":"Splatthy","bid":4418750,"buyout":4950000,"quantity":5,"timeLeft":"VERY_LONG","rand":0,"seed":2058173312},
{"auc":1972336707,"item":8486,"owner":"Zaruman","bid":351500,"buyout":450000,"quantity":1,"timeLeft":"VERY_LONG","rand":0,"seed":0},
{"auc":1972386682,"item":16249,"owner":"Huntez","bid":11250,"buyout":0,"quantity":1,"timeLeft":"VERY_LONG","rand":0,"seed":747154816},
{"auc":1972386894,"item":4338,"owner":"Huntez","bid":90284,"buyout":95038,"quantity":15,"timeLeft":"VERY_LONG","rand":0,"seed":944449152},
{"auc":1972337130,"item":8488,"owner":"Zaruman","bid":351500,"buyout":450000,"quantity":1,"timeLeft":"VERY_LONG","rand":0,"seed":0},
{"auc":1972336425,"item":8485,"owner":"Zaruman","bid":351500,"buyout":450000,"quantity":1,"timeLeft":"VERY_LONG","rand":0,"seed":0}]}
}

一行代码,把给定的JSON文件,生成对应的类单元,类名为TJSONData。

将上面的s变量,存在文件,就得到了生成的单元,加入到自己的项目中,就可以通过TJSONData类来访问对应的auctions.json中的内容了!

下面是生成的内容:

unit Unit2;

// ==========================================================================
// Generated by kbmMW ObjectNotation marshalling converter
// 11/03/2019 00:07:12
// ========================================================================== interface uses
Classes,
Generics.Collections,
kbmMWRTTI,
kbmMWObjectMarshal,
kbmMWDateTime,
kbmMWNullable; type TJSONData=class;
Trealm=class;
Talliance=class;
TauctionsList=class;
Tauctions=class;
Thorde=class;
Tneutral=class;
[kbmMW_Root('TJSONData',[mwrfIncludeOnlyTagged])]
TJSONData=class
private
Frealm:Trealm;
Falliance:Talliance;
Fhorde:Thorde;
Fneutral:Tneutral;
protected
procedure Setrealm(const AValue:Trealm); virtual;
procedure Setalliance(const AValue:Talliance); virtual;
procedure Sethorde(const AValue:Thorde); virtual;
procedure Setneutral(const AValue:Tneutral); virtual;
public
destructor Destroy; override; [kbmMW_Element('realm')]
property realm:Trealm read Frealm write Setrealm; [kbmMW_Element('alliance')]
property alliance:Talliance read Falliance write Setalliance; [kbmMW_Element('horde')]
property horde:Thorde read Fhorde write Sethorde; [kbmMW_Element('neutral')]
property neutral:Tneutral read Fneutral write Setneutral;
end; [kbmMW_Root('realm',[mwrfIncludeOnlyTagged])]
Trealm=class
private
Fname:kbmMWNullable<string>;
Fslug:kbmMWNullable<string>;
public
[kbmMW_Element('name')]
property name:kbmMWNullable<string> read Fname write Fname; [kbmMW_Element('slug')]
property slug:kbmMWNullable<string> read Fslug write Fslug;
end; [kbmMW_Root('alliance',[mwrfIncludeOnlyTagged])]
Talliance=class
private
Fauctions:TauctionsList;
protected
procedure Setauctions(const AValue:TauctionsList); virtual;
public
destructor Destroy; override; [kbmMW_Element('auctions')]
property auctions:TauctionsList read Fauctions write Setauctions;
end; [kbmMW_Child('auctions',[mwcfFlatten])]
TauctionsList=class(TObjectList<Tauctions>);
[kbmMW_Root('auctions',[mwrfIncludeOnlyTagged])]
Tauctions=class
private
FpetSpeciesId:kbmMWNullable<double>;
FpetBreedId:kbmMWNullable<double>;
FpetLevel:kbmMWNullable<double>;
FpetQualityId:kbmMWNullable<double>;
Fauc:kbmMWNullable<double>;
Fitem:kbmMWNullable<double>;
Fowner:kbmMWNullable<string>;
Fbid:kbmMWNullable<double>;
Fbuyout:kbmMWNullable<double>;
Fquantity:kbmMWNullable<double>;
FtimeLeft:kbmMWNullable<string>;
Frand:kbmMWNullable<double>;
Fseed:kbmMWNullable<double>;
public
[kbmMW_Element('petSpeciesId')]
property petSpeciesId:kbmMWNullable<double> read FpetSpeciesId write FpetSpeciesId; [kbmMW_Element('petBreedId')]
property petBreedId:kbmMWNullable<double> read FpetBreedId write FpetBreedId; [kbmMW_Element('petLevel')]
property petLevel:kbmMWNullable<double> read FpetLevel write FpetLevel; [kbmMW_Element('petQualityId')]
property petQualityId:kbmMWNullable<double> read FpetQualityId write FpetQualityId; [kbmMW_Element('auc')]
property auc:kbmMWNullable<double> read Fauc write Fauc; [kbmMW_Element('item')]
property item:kbmMWNullable<double> read Fitem write Fitem; [kbmMW_Element('owner')]
property owner:kbmMWNullable<string> read Fowner write Fowner; [kbmMW_Element('bid')]
property bid:kbmMWNullable<double> read Fbid write Fbid; [kbmMW_Element('buyout')]
property buyout:kbmMWNullable<double> read Fbuyout write Fbuyout; [kbmMW_Element('quantity')]
property quantity:kbmMWNullable<double> read Fquantity write Fquantity; [kbmMW_Element('timeLeft')]
property timeLeft:kbmMWNullable<string> read FtimeLeft write FtimeLeft; [kbmMW_Element('rand')]
property rand:kbmMWNullable<double> read Frand write Frand; [kbmMW_Element('seed')]
property seed:kbmMWNullable<double> read Fseed write Fseed;
end; [kbmMW_Root('horde',[mwrfIncludeOnlyTagged])]
Thorde=class
private
Fauctions:TauctionsList;
protected
procedure Setauctions(const AValue:TauctionsList); virtual;
public
destructor Destroy; override; [kbmMW_Element('auctions')]
property auctions:TauctionsList read Fauctions write Setauctions;
end; [kbmMW_Root('neutral',[mwrfIncludeOnlyTagged])]
Tneutral=class
private
Fauctions:TauctionsList;
protected
procedure Setauctions(const AValue:TauctionsList); virtual;
public
destructor Destroy; override; [kbmMW_Element('auctions')]
property auctions:TauctionsList read Fauctions write Setauctions;
end; implementation procedure TJSONData.Setrealm(const AValue:Trealm);
begin
if Assigned(Frealm) then
Frealm.Free;
Frealm:=AValue;
end; procedure TJSONData.Setalliance(const AValue:Talliance);
begin
if Assigned(Falliance) then
Falliance.Free;
Falliance:=AValue;
end; procedure TJSONData.Sethorde(const AValue:Thorde);
begin
if Assigned(Fhorde) then
Fhorde.Free;
Fhorde:=AValue;
end; procedure TJSONData.Setneutral(const AValue:Tneutral);
begin
if Assigned(Fneutral) then
Fneutral.Free;
Fneutral:=AValue;
end; destructor TJSONData.Destroy;
begin
Frealm.Free;
Falliance.Free;
Fhorde.Free;
Fneutral.Free;
inherited;
end; procedure Talliance.Setauctions(const AValue:TauctionsList);
begin
if Assigned(Fauctions) then
Fauctions.Free;
Fauctions:=AValue;
end; destructor Talliance.Destroy;
begin
Fauctions.Free;
inherited;
end; procedure Thorde.Setauctions(const AValue:TauctionsList);
begin
if Assigned(Fauctions) then
Fauctions.Free;
Fauctions:=AValue;
end; destructor Thorde.Destroy;
begin
Fauctions.Free;
inherited;
end; procedure Tneutral.Setauctions(const AValue:TauctionsList);
begin
if Assigned(Fauctions) then
Fauctions.Free;
Fauctions:=AValue;
end; destructor Tneutral.Destroy;
begin
Fauctions.Free;
inherited;
end; initialization
kbmMWRegisterKnownClasses([TMainClass,Trealm,Talliance,TauctionsList,Tauctions,Thorde,Tneutral]); end.

要实际读取文件,创建一个程序,将Unit2.pas添加到它,并编写以下代码:

procedure TForm1.Button1Click(Sender: TObject);
var
m:TkbmMWCustomRTTIMarshal;
o:TJSONData;
begin
m:=TkbmMWJSONMarshal.Create;
try
TkbmMWJSONMarshal(m).AnonymousRoot:=true;
o:=TkbmMWJSONMarshal(m).ValueFromUTF8File<TJSONData>('auctions.json');
// Your complete parsed file is now contained in the object instance o.
finally
o.Free;
m.Free;
end;
end;

下面是一个xml文件:

<?xml version="1.0"?>
<root>
<course>
<reg_num>10577</reg_num>
<subj>ANTH</subj>
<crse>211</crse>
<sect>F01</sect>
<title>Introduction to Anthropology</title>
<units>1.0</units>
<instructor>Brightman</instructor>
<days>M-W</days>
<time>
<start_time>03:10PM</start_time>
<end_time>04:30</end_time>
</time>
<place>
<building>ELIOT</building>
<room>414</room>
</place>
</course>
<course>
<reg_num>20573</reg_num>
<subj>ANTH</subj>
<crse>344</crse>
<sect>S01</sect>
<title>Sex and Gender</title>
<units>1.0</units>
<instructor>Makley</instructor>
<days>T-Th</days>
<time>
<start_time>10:30AM</start_time>
<end_time>11:50</end_time>
</time>
<place>
<building>VOLLUM</building>
<room>120</room>
</place>
</course>
<course>
<reg_num>10624</reg_num>
<subj>BIOL</subj>
<crse>431</crse>
<sect>F01</sect>
<title>Field Biology of Amphibians</title>
<units>0.5</units>
...
</course>
...
</root>

把上面xml内容生成类的代码:

var
s:string;
...
s:=TkbmMWXMLMarshal.GenerateDelphiClassFromFile('courses.xml','Unit3','XMLData');
...

把s变成存为Unit3.pas文件:

unit Unit3;

// ==========================================================================
// Generated by kbmMW ObjectNotation marshalling converter
// 10/03/2019 23:54:52
// ========================================================================== interface uses
Classes,
Generics.Collections,
kbmMWRTTI,
kbmMWObjectMarshal,
kbmMWDateTime,
kbmMWNullable; type Troot=class;
TcourseList=class;
Tcourse=class;
Ttime=class;
Tplace=class;
[kbmMW_Root('root',[mwrfIncludeOnlyTagged])]
Troot=class
private
Fcourse:TcourseList;
protected
procedure Setcourse(const AValue:TcourseList); virtual;
public
destructor Destroy; override; [kbmMW_Element('course')]
property course:TcourseList read Fcourse write Setcourse;
end; [kbmMW_Child('course',[mwcfFlatten])]
TcourseList=class(TObjectList<Tcourse>);
[kbmMW_Root('course',[mwrfIncludeOnlyTagged])]
Tcourse=class
private
Ftime:Ttime;
Fplace:Tplace;
Freg_num:kbmMWNullable<string>;
Fsubj:kbmMWNullable<string>;
Fcrse:kbmMWNullable<string>;
Fsect:kbmMWNullable<string>;
Ftitle:kbmMWNullable<string>;
Funits:kbmMWNullable<string>;
Finstructor:kbmMWNullable<string>;
Fdays:kbmMWNullable<string>;
Fxml_repository:kbmMWNullable<string>;
protected
procedure Settime(const AValue:Ttime); virtual;
procedure Setplace(const AValue:Tplace); virtual;
public
destructor Destroy; override; [kbmMW_Element('time')]
property time:Ttime read Ftime write Settime; [kbmMW_Element('place')]
property place:Tplace read Fplace write Setplace; [kbmMW_Element('reg_num')]
property reg_num:kbmMWNullable<string> read Freg_num write Freg_num; [kbmMW_Element('subj')]
property subj:kbmMWNullable<string> read Fsubj write Fsubj; [kbmMW_Element('crse')]
property crse:kbmMWNullable<string> read Fcrse write Fcrse; [kbmMW_Element('sect')]
property sect:kbmMWNullable<string> read Fsect write Fsect; [kbmMW_Element('title')]
property title:kbmMWNullable<string> read Ftitle write Ftitle; [kbmMW_Element('units')]
property units:kbmMWNullable<string> read Funits write Funits; [kbmMW_Element('instructor')]
property instructor:kbmMWNullable<string> read Finstructor write Finstructor; [kbmMW_Element('days')]
property days:kbmMWNullable<string> read Fdays write Fdays; [kbmMW_Element('xml_repository')]
property xml_repository:kbmMWNullable<string> read Fxml_repository write Fxml_repository;
end; [kbmMW_Root('time',[mwrfIncludeOnlyTagged])]
Ttime=class
private
Fstart_time:kbmMWNullable<string>;
Fend_time:kbmMWNullable<string>;
public
[kbmMW_Element('start_time')]
property start_time:kbmMWNullable<string> read Fstart_time write Fstart_time; [kbmMW_Element('end_time')]
property end_time:kbmMWNullable<string> read Fend_time write Fend_time;
end; [kbmMW_Root('place',[mwrfIncludeOnlyTagged])]
Tplace=class
private
Fbuilding:kbmMWNullable<string>;
Froom:kbmMWNullable<string>;
public
[kbmMW_Element('building')]
property building:kbmMWNullable<string> read Fbuilding write Fbuilding; [kbmMW_Element('room')]
property room:kbmMWNullable<string> read Froom write Froom;
end; implementation procedure Troot.Setcourse(const AValue:TcourseList);
begin
if Assigned(Fcourse) then
Fcourse.Free;
Fcourse:=AValue;
end; destructor Troot.Destroy;
begin
Fcourse.Free;
inherited;
end; procedure Tcourse.Settime(const AValue:Ttime);
begin
if Assigned(Ftime) then
Ftime.Free;
Ftime:=AValue;
end; procedure Tcourse.Setplace(const AValue:Tplace);
begin
if Assigned(Fplace) then
Fplace.Free;
Fplace:=AValue;
end; destructor Tcourse.Destroy;
begin
Ftime.Free;
Fplace.Free;
inherited;
end; initialization
kbmMWRegisterKnownClasses([Troot,TcourseList,Tcourse,Ttime,Tplace]); end.

读取和写入这个XML数据的Delphi代码:

procedure TForm1.Button2Click(Sender: TObject);
var
m:TkbmMWCustomRTTIMarshal;
o:Troot;
s:string;
begin
m:=TkbmMWXMLMarshal.Create;
try
o:=TkbmMWXMLMarshal(m).ValueFromFile<Troot>('courses.xml');
// o now contains all courses. s:=TkbmMWXMLMarshal(m).ValueToString(o);
// s now contains XML generated from o.
finally
o.Free;
m.Free;
end;
end;