JSON和数据集互相转换单元
如题......只是一个单元, 为了测试JSON单元性能的...
具体测试结果参考: http://www.cnblogs.com/lzl_17948876/p/3668052.html
代码中用到的SevenZIP单元在这里: http://www.cnblogs.com/lzl_17948876/p/3876160.html
unit DSCJSON; // *************************************************************************** // // TDataSet与JSON相互转换单元 // // 版本: 1.3 // 作者: 刘志林 // 修改日期: 2016-08-17 // QQ: 17948876 // E-mail: lzl_17948876@hotmail.com // 博客: http://www.cnblogs.com/lzl_17948876/ // // !!! 若有修改,请通知作者,谢谢合作 !!! // // --------------------------------------------------------------------------- // // 修改历史: // 1.3 // 去掉字符编码配置, 去掉二进制编码配置 // 增加对二进制字段压缩的支持(使用7-ZIP) // 优化了一些代码结构 // 1.2 // 支持QJSON // 增加SYSTEM.JSON单元支持(D10中新单元, 就是原有的DBXJSON) // 1.1 // 支持FireDAC // 增加DBXJSON单元支持 // 增加对NULL值字段支持 // 1.0: // 支持ADO/ClientDataset与JSON互相转换 // 使用SuperObject单元作为JSON解析单元 // // ***************************************************************************(* {$DEFINE FIREDAC} //{$DEFINE ADO} {$DEFINE QJSON} //{$DEFINE JSON_SO} //{$DEFINE JSON_DBX} //{$DEFINE JSON_SYS} {$IF DEFINED(JSON_DBX) OR DEFINED(JSON_SYS)} {$DEFINE SYSJSON} {$ENDIF} //{$DEFINE 7ZIP} interface uses SysUtils, Classes, DB, DBClient, DateUtils {$IFDEF JSON_DBX} , DBXJSON {$ENDIF} {$IFDEF JSON_SO} , superobject, Variants {$ENDIF} {$IFDEF FIREDAC} , FireDAC.Comp.DataSet {$ENDIF} {$IFDEF JSON_SYS} , System.JSON {$ENDIF} {$IFDEF QJSON} , QJSON {$ENDIF} {$IFDEF ADO} , ADODB {$ENDIF} , EncdDecd; /// <summary>将数据集转化为JSON数据</summary> /// <param name="ADataSet">TDataSet - 数据集</param> /// <param name="AJSON">WideString - 输出转换结果</param> /// <returns>转换结果 成功: True 失败: False</returns> function DataSetToJSON(ADataSet: TDataSet; var AJSON: WideString): Boolean; /// <summary>JSON数据转换为结果集</summary> /// <param name="AJSON">JSON数据</param> /// <param name="ADataSet">数据集</param> /// <returns>转换结果 成功: True 失败: False</returns> function JSONToDataSet(AJSON: WideString; ADataSet: TDataSet): Boolean; implementation {$IFDEF 7ZIP} uses SevenZIP; {$ENDIF} (* C: 配置表 C.BC BolbComp 二进制字段是否压缩 0:未压缩 1:已压缩 默认 0 C.CC CompClass 压缩类型 {使用7-ZIP压缩, 如果不打开7ZIP编译开关, 此控制无效认为不压缩} 空表示不压缩, 否则为7-ZIP压缩类型 默认 CLSID_CFormatGZip : TGUID = '{23170F69-40C1-278A-1000-000110EF0000}' T: 表结构表 T.N:列名 T.D:显示列名 T.T:列数据类型 Data.DB.TFieldType T.L:列数据长度 T.R:列值是否允许为空 R: 数据表 { "C":{"BC":0, "CM":"", "BE":0}, "T":[{"N":"FieldName", "D":"DisplayName", "T":0, "L":100, "R":1}], "R":[["Field1Value", "Field2Value"]] } *) const _FT_STRING = $00; {字符} _FT_INTEGER = $01; {整形} _FT_FLOAT = $02; {浮点} _FT_DATETIME = $03; {日期} _FT_BOOLEAN = $04; {布尔} _FT_BLOB = $05; {二进制} _FT_CURRENCY = $10; {金额} type TConfig = record BolbComp: Boolean; {二进制字段是否压缩} CompClass: string; {压缩模式 空表示不压缩, 否则为7-ZIP压缩类型} end; function JSONToDataSet(AJSON: WideString; ADataSet: TDataSet): Boolean; var nJDS: {$IFDEF SYSJSON}TJSONObject{$ENDIF} {$IFDEF JSON_SO}ISuperObject{$ENDIF} {$IFDEF QJSON}TQJson{$ENDIF} ; nConfig: TConfig; procedure _JTDConfig; var nJO: {$IFDEF SYSJSON}TJSONObject{$ENDIF} {$IFDEF JSON_SO}ISuperObject{$ENDIF} {$IFDEF QJSON}TQJson{$ENDIF} ; begin with nConfig do begin BolbComp := False; CompClass := ''; end; {$IFDEF SYSJSON} nJO := nJDS.GetValue('C') as TJSONObject; if nJO = nil then Exit; {$ENDIF} {$IFDEF JSON_SO} nJO := nJDS.N['C']; if nJO.DataType = stNull then Exit; {$ENDIF} {$IFDEF QJSON} nJO := nJDS.ItemByName('C'); if nJO.DataType = jdtNull then Exit; {$ENDIF} with nConfig do begin BolbComp := {$IFDEF SYSJSON}TJSONNumber(nJO.GetValue('BC')).AsInt{$ENDIF} {$IFDEF JSON_SO}nJO.I['BC']{$ENDIF} {$IFDEF QJSON}nJO.ItemByName('BC').AsInteger{$ENDIF} = 1; {$IFDEF 7ZIP} CompClass := {$IFDEF SYSJSON}nJO.GetValue('CC').Value{$ENDIF} {$IFDEF JSON_SO}nJO['CC'].AsString{$ENDIF} {$IFDEF QJSON}nJO.ItemByName('CC').AsString{$ENDIF} ; {$ELSE} CompClass := ''; {$ENDIF} end; end; function _JTDStepField: Boolean; var nFName, nFDisplay: String; i, nFLength: Integer; nFType: Byte; nFD: TFieldDef; nFRequired: Boolean; {$IFDEF SYSJSON} nJA: TJSONArray; nJO: TJSONObject; nJV: TJSONValue; nJP: TJSONPair; {$ENDIF} {$IFDEF JSON_SO} nJA: TSuperArray; nJO, nJR: ISuperObject; {$ENDIF} {$IFDEF QJSON} nJO, nJR: TQJson; {$ENDIF} begin Result := False; ADataSet.Close; {$IFDEF SYSJSON} nJA := nJDS.GetValue('T') as TJSONArray; if nJA = nil then Exit; {$ENDIF} {$IFDEF JSON_SO} nJO := nJDS.N['T']; if nJO.DataType = stNull then Exit; {$ENDIF} {$IFDEF QJSON} nJO := nJDS.ItemByName('T'); if nJO.DataType = jdtNull then Exit; {$ENDIF} ADataSet.FieldDefs.BeginUpdate; try ADataSet.FieldDefs.Clear; {拆解Field} {$IFDEF SYSJSON} for i := 0 to nJA.Size - 1 do begin nJO := nJA.Get(i) as TJSONObject; nFName := nJO.GetValue('N').Value; nFDisplay := nJO.GetValue('D').Value; nFType := TJSONNumber(nJO.GetValue('T')).AsInt; nFLength := TJSONNumber(nJO.GetValue('L')).AsInt; nFRequired := Boolean(TJSONNumber(nJO.GetValue('R')).AsInt); {$ENDIF} {$IFDEF JSON_SO} nJA := nJO.AsArray; for i := 0 to nJA.Length - 1 do begin nJR := nJA[i]; nFName := nJR['N'].AsString; nFDisplay := nJR['D'].AsString; nFType := nJR['T'].AsInteger; nFLength := nJR['L'].AsInteger; nFRequired := Boolean(nJR['R'].AsInteger); {$ENDIF} {$IFDEF QJSON} for i := 0 to nJO.Count - 1 do begin nJR := nJO.Items[i]; nFName := nJR.ItemByName('N').AsString; nFDisplay := nJR.ItemByName('D').AsString; nFType := nJR.ItemByName('T').AsInteger; nFLength := nJR.ItemByName('L').AsInteger; nFRequired := Boolean(nJR.ItemByName('R').AsInteger); {$ENDIF} nFD := ADataSet.FieldDefs.AddFieldDef; with nFD do try Name := nFName; case nFType of _FT_INTEGER: DataType := ftLargeint; _FT_FLOAT: DataType := ftFloat; _FT_DATETIME: DataType := ftDateTime; _FT_BOOLEAN: DataType := ftBoolean; _FT_BLOB: DataType := ftBlob; _FT_CURRENCY: DataType := ftCurrency; else DataType := ftString; Size := nFLength; end; Required := nFRequired; DisplayName := nFDisplay; except DisposeOf; end; end; finally ADataSet.FieldDefs.EndUpdate; end; Result := True; end; function _JTDStepRecord: Boolean; var nFName, nStr: String; i, j: Integer; nField: TField; nMSI, nMSO: TMemoryStream; {$IFDEF 7ZIP} nCItemIndex: Integer; nMSC: TMemoryStream; {解压缩用} {$ENDIF} nJRA: {$IFDEF SYSJSON}TJSONArray{$ENDIF} {$IFDEF JSON_SO}TSuperArray{$ENDIF} {$IFDEF QJSON}TQJson{$ENDIF} ; {$IFDEF SYSJSON} nJA: TJSONArray; {$ENDIF} {$IFDEF JSON_SO} nJA: TSuperArray; nJO, nJR: ISuperObject; {$ENDIF} {$IFDEF QJSON} nJO: TQJson; {$ENDIF} begin Result := False; {$IFDEF SYSJSON} nJA := nJDS.GetValue('R') as TJSONArray; if nJA = nil then Exit; {$ENDIF} {$IFDEF JSON_SO} nJO := nJDS.N['R']; if nJO.DataType = stNull then Exit; nJA := nJO.AsArray; {$ENDIF} {$IFDEF QJSON} nJO := nJDS.ItemByName('R'); if nJO.DataType = jdtNull then Exit; {$ENDIF} nMSO := TMemoryStream.Create; nMSI := TStringStream.Create; {$IFDEF 7ZIP} nMSC := TMemoryStream.Create; {$ENDIF} ADataSet.DisableControls; try for i := 0 to {$IFDEF SYSJSON}nJA.Size - 1{$ENDIF} {$IFDEF JSON_SO}nJA.Length - 1{$ENDIF} {$IFDEF QJSON}nJO.Count - 1{$ENDIF} do begin nJRA := {$IFDEF SYSJSON}nJA.Get(i) as TJSONArray{$ENDIF} {$IFDEF JSON_SO}nJA[i].AsArray{$ENDIF} {$IFDEF QJSON}nJO.Items[i]{$ENDIF} ; ADataSet.Append; for j := 0 to ADataSet.Fields.Count - 1 do begin nField := ADataSet.Fields[j]; nFName := nField.FieldName; if {$IFDEF SYSJSON}nJRA.Get(j).Null{$ENDIF} {$IFDEF JSON_SO}nJRA[j].DataType = stNull{$ENDIF} {$IFDEF QJSON}nJRA[j].DataType = jdtNull{$ENDIF} then begin nField.SetData(nil); end else begin case nField.DataType of ftLargeint: begin nField.Value := {$IFDEF SYSJSON}TJSONNumber(nJRA.Get(j)).AsInt64{$ENDIF} {$IFDEF JSON_SO}nJRA[j].AsInteger{$ENDIF} {$IFDEF QJSON}nJRA.Items[j].AsInteger{$ENDIF} ; end; ftFloat, ftCurrency: begin nField.Value := {$IFDEF SYSJSON}TJSONNumber(nJRA.Get(j)).AsDouble{$ENDIF} {$IFDEF JSON_SO}nJRA[j].AsDouble{$ENDIF} {$IFDEF QJSON}nJRA.Items[j].AsFloat{$ENDIF} ; end; ftDateTime: begin nField.Value := UnixToDateTime( {$IFDEF SYSJSON}TJSONNumber(nJRA.Get(j)).AsInt64{$ENDIF} {$IFDEF JSON_SO}nJRA[j].AsInteger{$ENDIF} {$IFDEF QJSON}nJRA.Items[j].AsInt64{$ENDIF} ); end; ftBoolean: begin nField.Value := Boolean( {$IFDEF SYSJSON}TJSONNumber(nJRA.Get(j)).AsInt{$ENDIF} {$IFDEF JSON_SO}nJRA[j].AsInteger{$ENDIF} {$IFDEF QJSON}nJRA.Items[j].AsInteger{$ENDIF} ); end; ftBlob: begin nMSI.Clear; nMSO.Clear; nStr := {$IFDEF SYSJSON}TJSONString(nJRA.Get(j)).Value{$ENDIF} {$IFDEF JSON_SO}nJRA[j].AsString{$ENDIF} {$IFDEF QJSON}nJRA.Items[j].AsString{$ENDIF} ; nMSI.Write(nStr[1], Length(nStr) * SizeOf(Char)); nMSI.Position := 0; nMSO.Clear; {$IFDEF 7ZIP} if nConfig.CompClass = '' then begin {$ENDIF} DecodeStream(nMSI, nMSO); {$IFDEF 7ZIP} end else try nMSC.Clear; DecodeStream(nMSI, nMSC); nMSC.Position := 0; with CreateInArchive(TGUID.Create(nConfig.CompClass)) do begin OpenStream(T7zStream.Create(nMSC, soReference)); for nCItemIndex := 0 to NumberOfItems - 1 do if not ItemIsFolder[nCItemIndex] then begin ExtractItem(nCItemIndex, nMSO, False); Break; end; end; except {此处解压缩异常后, 默认不写入数据, 根据实际情况进行处理} nMSO.Clear; end; {$ENDIF} nMSO.Position := 0; TBlobField(nField).LoadFromStream(nMSO); end; else nField.Value := {$IFDEF SYSJSON}TJSONString(nJRA.Get(j)).Value{$ENDIF} {$IFDEF JSON_SO}nJRA[j].AsString{$ENDIF} {$IFDEF QJSON}nJRA.Items[j].AsString{$ENDIF} ; end; end; end; ADataSet.Post; end; ADataSet.First; finally ADataSet.EnableControls; nMSO.Free; nMSI.Free; {$IFDEF 7ZIP} nMSC.Free; {$ENDIF} end; Result := True; end; begin if ADataSet = nil then Exit; {$IFDEF SYSJSON} nJDS := TJSONObject.ParseJSONValue(AJSON) as TJSONObject; try {$ENDIF} {$IFDEF JSON_SO} nJDS := SO(AJSON); {$ENDIF} {$IFDEF QJSON} nJDS := TQJson.Create; nJDS.Parse(AJSON); try {$ENDIF} try _JTDConfig; if ADataSet is TCustomClientDataSet then begin Result := _JTDStepField; if Result then begin TCustomClientDataSet(ADataSet).CreateDataSet; Result := _JTDStepRecord; end; end {$IFDEF ADO} else if ADataSet is TADODataSet then begin Result := _JTDStepField; if Result then begin TADODataSet(ADataSet).CreateDataSet; Result := _JTDStepRecord; end; end {$ENDIF} {$IFDEF FIREDAC} else if ADataSet is TFDDataSet then begin Result := _JTDStepField; if Result then begin TFDDataSet(ADataSet).CreateDataSet; Result := _JTDStepRecord; end; end {$ENDIF} else Result := False; except Result := False; end; {$IFDEF SYSJSON} finally nJDS.Free; end; {$ENDIF} {$IFDEF QJSON} finally nJDS.Free; end; {$ENDIF} end; function DataSetToJSON(ADataSet: TDataSet; var AJSON: WideString): Boolean; var nJA, nJRA: {$IFDEF SYSJSON}TJSONArray{$ENDIF} {$IFDEF JSON_SO}TSuperArray{$ENDIF} {$IFDEF QJSON}TQJson{$ENDIF} ; nJDS: {$IFDEF SYSJSON}TJSONObject{$ENDIF} {$IFDEF JSON_SO}ISuperObject{$ENDIF} {$IFDEF QJSON}TQJson{$ENDIF} ; {$IFDEF SYSJSON} nJO: TJSONObject; {$ENDIF} {$IFDEF JSON_SO} nJR: ISuperObject; {$ENDIF} i: Integer; nTitle, nStr, nFDisplay: string; nField: TField; nFT: Byte; nMSI: TMemoryStream; nSSO: TStringStream; nCompClassStr: string; {$IFDEF 7ZIP} nMSC: TMemoryStream; {解压缩用} {$ENDIF} const _DEF_TITLE = '{"C":{"BC":0,"CC":"%s"},"T":[],"R":[]}'; _DEf_RECORD = '{"N":"%s","D":"%s","T":%d,"L":%d,"R":%d}'; begin Result := False; {$IFDEF 7ZIP} nCompClassStr := CLSID_CFormatGZip.ToString; {$ELSE} nCompClassStr := ''; {$ENDIF} nTitle := Format(_DEF_TITLE, [nCompClassStr]); {$IFDEF SYSJSON} nJDS := TJSONObject.ParseJSONValue(nTitle) as TJSONObject; {$ENDIF} {$IFDEF JSON_SO} nJDS := SO(nTitle); {$ENDIF} {$IFDEF QJSON} nJDS := TQJson.Create; nJDS.Parse(nTitle); {$ENDIF} ADataSet.DisableControls; nMSI := TMemoryStream.Create; nSSO := TStringStream.Create; {$IFDEF 7ZIP} nMSC := TMemoryStream.Create; {$ENDIF} try nJA := {$IFDEF SYSJSON}nJDS.GetValue('T') as TJSONArray{$ENDIF} {$IFDEF JSON_SO}nJDS.A['T']{$ENDIF} {$IFDEF QJSON}nJDS.ItemByName('T'){$ENDIF} ; AJSON := ''; try ADataSet.First; for i := 0 to ADataSet.Fields.Count - 1 do begin nField := ADataSet.Fields[i]; case nField.DataType of ftSmallint, ftInteger, ftWord, ftLargeint, ftLongWord, ftShortint, ftByte: nFT := _FT_INTEGER; ftFloat, ftBCD, ftSingle, ftExtended: nFT := _FT_FLOAT; ftDate, ftTime, ftDateTime: nFT := _FT_DATETIME; ftBoolean: nFT := _FT_BOOLEAN; ftBlob, ftMemo, ftGraphic: nFT := _FT_BLOB; ftCurrency: nFT := _FT_CURRENCY; else nFT := _FT_STRING; end; if nField.DisplayLabel = nField.FieldName then nFDisplay := '' else nFDisplay := nField.DisplayLabel; nStr := Format(_DEf_RECORD, [nField.FieldName, nFDisplay, nFT, nField.DataSize, Byte(nField.Required)]); {$IFDEF SYSJSON} nJA.AddElement(TJSONObject.ParseJSONValue(nStr)); {$ENDIF} {$IFDEF JSON_SO} nJA.Add(SO(nStr)); {$ENDIF} {$IFDEF QJSON} nJA.Add.Parse(nStr); {$ENDIF} end; nJA := {$IFDEF SYSJSON}nJDS.GetValue('R') as TJSONArray{$ENDIF} {$IFDEF JSON_SO}nJDS.A['R']{$ENDIF} {$IFDEF QJSON}nJDS.ItemByName('R'){$ENDIF} ; while not ADataSet.Eof do begin {$IFDEF SYSJSON} nJRA := TJSONArray.Create; nJA.AddElement(nJRA); {$ENDIF} {$IFDEF JSON_SO} nJR := SA([]); nJA.Add(nJR); nJRA := nJR.AsArray; {$ENDIF} {$IFDEF QJSON} nJRA := nJA.Add('', jdtArray); {$ENDIF} for i := 0 to ADataSet.Fields.Count - 1 do begin nField := ADataSet.Fields[i]; if nField.IsNull then begin {$IFDEF SYSJSON} nJRA.AddElement(TJSONNull.Create); {$ENDIF} {$IFDEF JSON_SO} nJRA.Add(SO(NULL)); {$ENDIF} {$IFDEF QJSON} nJRA.Add('', jdtNull); {$ENDIF} end else begin case nField.DataType of ftSmallint, ftInteger, ftWord, ftLargeint, ftLongWord, ftShortint, ftByte: begin {$IFDEF SYSJSON} nJRA.Add(nField.AsInteger); {$ENDIF} {$IFDEF JSON_SO} nJRA.Add(SO(nField.AsInteger)); {$ENDIF} {$IFDEF QJSON} nJRA.Add.AsInteger := nField.AsInteger; {$ENDIF} end; ftFloat, ftBCD, ftSingle, ftExtended, ftCurrency: begin {$IFDEF SYSJSON} nJRA.Add(nField.AsFloat); {$ENDIF} {$IFDEF JSON_SO} nJRA.Add(SO(nField.AsFloat)); {$ENDIF} {$IFDEF QJSON} nJRA.Add.AsFloat := nField.AsFloat; {$ENDIF} end; ftDate, ftTime, ftDateTime: begin {$IFDEF SYSJSON} nJRA.Add(DateTimeToUnix(nField.AsDateTime)); {$ENDIF} {$IFDEF JSON_SO} nJRA.Add(SO(DateTimeToUnix(nField.AsDateTime))); {$ENDIF} {$IFDEF QJSON} nJRA.Add.AsInt64 := DateTimeToUnix(nField.AsDateTime); {$ENDIF} end; ftBlob, ftMemo, ftGraphic: begin nMSI.Clear; nSSO.Clear; {$IFDEF 7ZIP} if nCompClassStr <> '' then try nMSC.Clear; TBlobField(nField).SaveToStream(nMSC); nMSC.Position := 0; with CreateOutArchive(TGUID.Create(nCompClassStr)) do begin AddStream(nMSC, soReference, faArchive, CurrentFileTime, CurrentFileTime, ExtractFilePath(ParamStr(0)), False, False); SaveToStream(nMSI); end; except nMSI.Clear; end else begin {$ENDIF} TBlobField(nField).SaveToStream(nMSI); {$IFDEF 7ZIP} end; {$ENDIF} nMSI.Position := 0; EncodeStream(nMSI, nSSO); {$IFDEF SYSJSON} nJRA.Add(nSSO.DataString); {$ENDIF} {$IFDEF JSON_SO} nJRA.Add(SO(nSSO.DataString)); {$ENDIF} {$IFDEF QJSON} nJRA.Add('', nSSO.DataString); {$ENDIF} end; else {$IFDEF SYSJSON} nJRA.Add(nField.AsString); {$ENDIF} {$IFDEF JSON_SO} nJRA.Add(SO(nField.AsString)); {$ENDIF} {$IFDEF QJSON} nJRA.Add('', nField.AsString); {$ENDIF} end; end; end; ADataSet.Next; end; AJSON := {$IFDEF SYSJSON}nJDS.ToString{$ENDIF} {$IFDEF JSON_SO}nJDS.AsJSon(False, False){$ENDIF} {$IFDEF QJSON}nJDS.Encode(False){$ENDIF} ; Result := True; except end; finally {$IFDEF 7ZIP} nMSC.Free; {$ENDIF} nMSI.Free; nSSO.Free; ADataSet.EnableControls; {$IFDEF SYSJSON} nJDS.Free; {$ENDIF} {$IFDEF QJSON} nJDS.Free; {$ENDIF} end; end; end.
--------------------------------------------------------------------------------------------------
作者:黑暗煎饼果子
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
--------------------------------------------------------------------------------------------------