JSON Superobject Research 2: Data sets and JSON objects are transferred to each other
JSON can not completely replace XML, but is definitely the future trend, its advantages are simple, small size, faster resolution, the resolution occupies less resources. In Delphi, datasets are the most common way of accessing data. Therefore, we must establish the relationship between JSON and Tdataset, and realize the communication and transformation between the data. It is important to note that this is only the normal conversion between Tdataset and JSON, since CDs contains delta packets, whose data formats are far more complex than ordinary tdataset. The following program, perhaps you have different ideas, if your ideas are better and faster, welcome to discuss together. Today is the last 10 minutes of 2009, the important thing is not to write a blog, but to say to everyone "good luck in the new Year, career success"!
The dataset field information is a complete dictionary information. Therefore, we must also establish the dictionary information in JSON in order to create the field information of the dataset. We set its JSON information as follows:
cols:[field List information], such as:
"Cols": [{"Jsontype": "Integer", "Fieldindex": 0, "FieldType": "Integer", "FieldSize": 0, "FieldName": "ID", "Required": false},{"Jsontype": "string", "Fieldindex": 1, "FieldType": "string", "FieldSize": +, "FieldName": "Title", "Required" : false},{"Jsontype": "Variant", "Fieldindex": 2, "FieldType": "Blob", "FieldSize": 0, "FieldName": "Picture", "Required" : false}]
The data information is the node of the database, and it is also an array nesting record information:
"Data": [Recordset information]
Say less nonsense, directly on the code:
Unit Udbjson;
Interface
Uses
Sysutils,classes,variants,db,dbclient,superobject;
Type
Ttablejson = Class
Private
Const CSTFIELDTYPE = ' FieldType ';
Const CSTFIELDNAME = ' FieldName ';
Const CSTFIELDSIZE = ' FieldSize ';
Const CSTJSONTYPE = ' Jsontype ';
Const cstrequired = ' Required ';
Const CSTFIELDINDEX = ' Fieldindex ';
Const cstcols= ' Cols ';
Const cstdata= ' Data ';
Public
class function Jsonfromdataset (Dataset:tdataset): string;
class function Createfieldbyjson (fields:tfielddefs; Colsjson:isuperobject): Boolean;
class function Importdatafromjson (dataset:tdataset;datajson:isuperobject): Integer;
class function Cdsfromjson (Cds:tclientdataset; Json:isuperobject): Boolean;
class function GetValue (Json:isuperobject;const name:string): Variant;
class function Createjsonvalue (Json:isuperobject;const name:string;const value:variant): Boolean;
class function Createjsonvaluebyfield (Json:isuperobject; Field:tfield): Boolean;
class function Getvalue2field (Field:tfield; Jsonvalue:isuperobject): Variant;
End
Implementation
Uses TYPINFO,ENCDDECD;
{Ttablejson}
Class function Ttablejson.cdsfromjson (Cds:tclientdataset;
Json:isuperobject): Boolean;
var
colsjson:isuperobject;
Begin
Result: = False;
If Json = nil then
Exit;
Cds. Close;
CDS. Data: = Null;
//Create field
Colsjson: = Json.o[cstcols];
Createfieldbyjson (CDS. Fielddefs,colsjson);
If CDS. Fielddefs.count >0 then
CDS. CreateDataSet;
Importdatafromjson (Cds,json.o[cstdata]);
Result: = True;
End;
class function Ttablejson.createfieldbyjson (fields:tfielddefs;
Colsjson:isuperobject): Boolean;
Var
Subjson:isuperobject;
Ft:tfieldtype;
Begin
Result: = False;
Fields.DataSet.Close;
Fields.clear;
For Subjson in Colsjson do
Begin
FT: = Tfieldtype (GetEnumValue (TypeInfo (Tfieldtype), ' ft ' +subjson.s[cstfieldtype]);
If ft= ftautoinc then//increment field cannot be entered and must be changed
FT: = Ftinteger;
Fields.Add (subjson.s[cstfieldname],ft,subjson.i[cstfieldsize],subjson.b[cstrequired]);
End
Result: = True;
End
class function Ttablejson.createjsonvalue (Json:isuperobject;
Const name:string; Const value:variant): Boolean;
Begin
Result: = False;
Json.o[name]: = SO (Value);
Result: = True;
End
class function Ttablejson.createjsonvaluebyfield (Json:isuperobject;
Field:tfield): Boolean;
Begin
Result: = False;
If Field is Tdatetimefield then
Json.o[field.fieldname]: = SO (field.asdatetime)
else if Field is Tblobfield then
Json.s[field.fieldname]: = encodestring (field.asstring)
Else
Json.o[field.fieldname]: = SO (Field.value);
Result: = True;
End
class function Ttablejson.getvalue (
Json:isuperobject;const name:string): Variant;
Begin
Case Json.datatype of
Stnull:result: = Null;
Stboolean:result: = Json.b[name];
Stdouble:result: = Json.d[name];
Stcurrency:result: = Json.c[name];
Stint:result: = Json.i[name];
Ststring:result: = Json.s[name];
End
End
class function Ttablejson.getvalue2field (Field:tfield; Jsonvalue:isuperobject): Variant;
Begin
If Jsonvalue.datatype = Stnull Then
Result: = Null
else if Field is Tdatetimefield then
Result: = Javatodelphidatetime (Jsonvalue.asinteger)
else if (field is Tintegerfield) or (field was Tlargeintfield) then
Result: = Jsonvalue.asinteger
else if Field is Tnumericfield then
Result: = jsonvalue.asdouble
else if Field is Tbooleanfield then
Result: = Jsonvalue.asboolean
else if Field is Tstringfield then
Result: = jsonvalue.asstring
else if Field is Tblobfield then
Result: = decodestring (jsonvalue.asstring)
End
class function Ttablejson.importdatafromjson (Dataset:tdataset;
Datajson:isuperobject): Integer;
Var
Subjson:isuperobject;
I:integer;
Iter:tsuperobjectiter;
Begin
If not dataset.active then
Dataset.open;
Dataset.disablecontrols;
Try
For Subjson in Datajson do
Begin
Dataset.append;
If Objectfindfirst (Subjson,iter) Then
Begin
Repeat
If Dataset.findfield (ITER). Ite.Current.Name) <>nil Then
Dataset.findfield (ITER). Ite.Current.Name). Value: =
Getvalue2field (
Dataset.findfield (ITER). Ite.Current.Name),
Iter. Ite.Current.Value);
Until not Objectfindnext (ITER);
End
Dataset.post;
End
Finally
Dataset.enablecontrols;
End
End
class function Ttablejson.jsonfromdataset (Dataset:tdataset): string;
Procedure Getfieldtypeinfo (Field:tfield;var fieldtyp,jsontyp:string);
Begin
Fieldtyp: = Getenumname (TypeInfo (Tfieldtype), Ord (Field.datatype));
Delete (fieldtyp,1,2);
If Field is Tstringfield then
Jsontyp: = ' string '
else if Field is Tdatetimefield then
Jsontyp: = ' integer '
else if (field is Tintegerfield) or (field was Tlargeintfield) then
Jsontyp: = ' integer '
else if Field is Tcurrencyfield then
Jsontyp: = ' Currency '
else if Field is Tnumericfield then
Jsontyp: = ' Double '
else if Field is Tbooleanfield then
Jsontyp: = ' Boolean '
Else
Jsontyp: = ' variant ';
End
Var
Sj,aj,sj2:isuperobject;
I:integer;
fieldtyp,jsontyp:string;
List:tstringlist;
Begin
SJ: = SO ();
Create columns
AJ: = SA ([]);
List: = tstringlist.create;
Try
list.sorted: = True;
For I: = 0 to Dataset.fieldcount-1 do
Begin
SJ2: = SO ();
Getfieldtypeinfo (Dataset.fields[i],fieldtyp,jsontyp);
Sj2. S[cstfieldname]: = Dataset.fields[i]. FieldName;
Sj2. S[cstfieldtype]: = Fieldtyp;
Sj2. S[cstjsontype]: = Jsontyp;
Sj2. I[cstfieldsize]: = Dataset.fields[i]. Size;
Sj2. B[cstrequired]: = Dataset.fields[i]. Required;
Sj2. I[cstfieldindex]: = Dataset.fields[i]. Index;
Aj. Asarray.add (SJ2);
List.add (Dataset.fields[i]. fieldname+ ' = ' +jsontyp);
End
Sj. o[' Cols ']: = AJ;
To create data for a dataset
Dataset.disablecontrols;
Dataset.first;
AJ: = SA ([]);
While not dataset.eof do
Begin
SJ2: = SO ();
For I: = 0 to Dataset.fieldcount-1 do
Begin
Sj2. S[inttostr (Dataset.fields[i]. Index)]: = Vartostrdef (Dataset.fields[i]. Value, ');
If Varisnull (Dataset.fields[i]. Value) Then
Sj2. O[dataset.fields[i]. FieldName]: = SO (Null)
Else
Begin
Createjsonvaluebyfield (Sj2,dataset.fields[i]);
End
End
Aj. Asarray.add (SJ2);
Dataset.next;
End
Sj. o[' Data ': = AJ;
Result: = SJ. asstring;
Finally
List.free;
Dataset.enablecontrols;
End
End
End.
Invocation Example:
DataSet to JSON object or JSON text
Var
Json:ttablejson;
s:string;
Begin
S: = json. Jsonfromdataset (ADODATASET1);
Read the string s in Tstringstream, save it as text, and look at its format.
End
JSON object or text, loading to the dataset
Var
Json:isuperobject;
Begin
JSON: = Tsuperobject.parsefile (' json.txt ', False);
Ttablejson.cdsfromjson (Cdsjson,json);
End
JSON Superobject Research 2: Data sets and JSON objects are transferred to each other