JsonDataObjects序列和还原

JsonDataObjects号称DELPHI最快的JSON库,且支持跨平台。

// cxg 2017-9-12
// Use JsonDataObjects(cross platform json library)
// Use delphi 10.2.1

unit ujson;

interface

uses
System.SysUtils, soap.EncdDecd, Web.HTTPApp, System.NetEncoding, Data.DB,
System.Classes, JsonDataObjects;

// {"data":[{"field1":value1,"field2":value2}]};
function datasetToJson(dataset: TDataSet): string;

// {"data":[{"field1":value1,"field2":value2}]};
procedure jsonToDataset(const json: string; dataset: TDataSet);

// {"cols":[{"name":"field1","size":0,"type":"int"}]"data":[{"field1":value1}]};
function datasetToJsonCols(dataset: TDataSet): string;

// {
// "update":[{"table":"表1","where":"字段1=1","字段1":"1","字段2":0}]
// ,"insert":[{"table":"表1","字段1":"1","字段2":0}]
// ,"delete":[{"table":"表1","where":"字段1=1"}]
// };
procedure parseJsonSql(const json: string; outsql: TStrings);

implementation

procedure parseJsonSql(const json: string; outsql: TStrings);
// {
// "update":[{"table":"表1","where":"字段1=1","字段1":"1","字段2":0}]
// ,"insert":[{"table":"表1","字段1":"1","字段2":0}]
// ,"delete":[{"table":"表1","where":"字段1=1"}]
// };
var
obj, childobj: TJsonObject;
tablename, sql, lname, lvalue, where: string;
i, j: Integer;
function _getValue(value: PJsonDataValue): string;
{
TJsonDataType = (
jdtNone, jdtString, jdtInt, jdtLong, jdtULong, jdtFloat, jdtDateTime
, jdtBool, jdtArray, jdtObject
);
}
begin
case Value.Typ of
jdtString: Result := QuotedStr(UTF8ToString(rawbytestring(TNetEncoding.URL.Decode(value.Value)))); // 解码
jdtBool: Result := BoolToStr(value.BoolValue);
jdtFloat: Result := FloatToStr(value.FloatValue);
jdtInt, jdtLong, jdtULong: Result := IntToStr(value.IntValue);
jdtDateTime: Result := DateTimeToStr(value.DateTimeValue);
end;
end;
begin
if outsql = nil then
Exit;
outsql.Clear;
obj := TJsonObject.Parse(json) as TJsonObject;
try
// 解析并生成insert sql begin-----------------------------------
for i := 0 to obj.A['insert'].Count - 1 do
begin
childobj := obj.A['insert'].O[i];
lname := '';
lvalue := '';
for j := 0 to childobj.Count - 1 do
begin
if childobj.Names[j] = 'table' then
begin
tablename := childobj.Items[j].Value;
Continue;
end;
if lname = '' then
lname := childobj.Names[j]
else
lname := lname + ',' + childobj.Names[j];
if lvalue = '' then
lvalue := _getValue(childobj.Items[j])
else
lvalue := lvalue + ',' + _getValue(childobj.Items[j]);
end;
sql := 'insert into ' + tablename + ' (' + lname + ') values (' + lvalue + ')';
outsql.Add(sql);
end;
// 解析并生成insert sql end----------------------------------------
// 解析并生成update sql begin---------------------------------------
for i := 0 to obj.A['update'].Count - 1 do
begin
childobj := obj.A['update'].O[i];
lname := '';
lvalue := '';
for j := 0 to childobj.Count - 1 do
begin
if childobj.Names[j] = 'table' then
begin
tablename := childobj.Items[j].Value;
Continue;
end
else
if childobj.Names[j] = 'where' then
begin
where := childobj.Items[j].Value;
Continue;
end;
if lname = '' then
lname := childobj.Names[j] + '=' + _getValue(childobj.Items[j])
else
lname := lname + ',' + childobj.Names[j] + '=' + _getValue(childobj.Items[j]);
end;
sql := 'update ' + tablename + ' set ' + lname + ' where ' + where;
outsql.Add(sql);
end;
// 解析并生成update sql end--------------------------------------------
// 解析并生成delete sql begin--------------------------------------------
for i := 0 to obj.A['delete'].Count - 1 do
begin
childobj := obj.A['delete'].O[i];
lname := '';
lvalue := '';
for j := 0 to childobj.Count - 1 do
begin
if childobj.Names[j] = 'table' then
begin
tablename := childobj.Items[j].Value;
Continue;
end
else
if childobj.Names[j] = 'where' then
begin
where := childobj.Items[j].Value;
Continue;
end;
end;
sql := 'delete from ' + tablename + ' where ' + where;
outsql.Add(sql);
end;
// 解析并生成delete sql end-------------------------------------------
finally
obj.free;
end;
end;

function datasetToJsonCols(dataset: TDataSet): string;
// {"cols":[{"name":"field1","size":0,"type":"int"}]"data":[{"field1":value1}]};
var
i: Integer;
obj, childobj: TJsonObject;
field: TField;
blob: TStringStream;

function _getFieldType(fld: TField): string;
begin
case fld.DataType of
ftBoolean:
Result := 'bool';
ftSmallint, ftInteger, ftWord, ftAutoInc:
Result := 'int';
ftLargeint:
Result := 'int64';
ftFloat, ftBCD, ftCurrency:
Result := 'float';
ftTimeStamp, ftDate, ftTime, ftDateTime:
Result := 'datetime';
ftString, ftFixedChar, ftMemo, ftWideString:
Result := 'string';
ftBytes, ftVarBytes, ftBlob, ftGraphic, ftOraBlob, ftOraClob:
Result := 'blob';
end;
end;

begin
// {"cols":[{"name":"c1","size":0,"type":"int"}]"data":[{"c1":1}]};
Result := '{"result":"false"}';
if (dataset = nil) or (not dataset.Active) then
Exit;
obj := TJsonObject.Create;
obj.A['cols'];
obj.A['data'];
dataset.First;
for i := 0 to dataset.FieldCount - 1 do // fill cols array
begin
field := dataset.Fields[i];
childobj := obj.A['cols'].AddObject;
childobj.S['name'] := field.FieldName;
childobj.I['size'] := field.Size;
childobj.S['type'] := _getFieldType(field);
childobj.B['required'] := field.Required;
childobj.B['readonly'] := field.ReadOnly;
end;
// fill data array
dataset.First;
while not dataset.Eof do
begin
childobj := obj.A['data'].AddObject;
for i := 0 to dataset.FieldCount - 1 do
begin
field := dataset.Fields[i];
if field.IsNull then
childobj.S[field.FieldName] := ''
else
begin
case field.DataType of
ftBoolean:
childobj.B[field.FieldName] := field.AsBoolean;
ftSmallint, ftInteger, ftWord, ftAutoInc:
childobj.I[field.FieldName] := field.AsInteger;
ftLargeint:
childobj.L[field.FieldName] := TLargeintField(field).AsLargeInt;
ftFloat, ftBCD, ftCurrency:
childobj.F[field.FieldName] := field.AsFloat;
ftTimeStamp, ftDate, ftTime, ftDateTime:
childobj.D[field.FieldName] := field.AsDateTime;
ftString, ftFixedChar, ftMemo, ftWideString:
childobj.S[field.FieldName] := TNetEncoding.URL.Encode(string(UTF8Encode(field.AsString))); // 编码
ftBytes, ftVarBytes, ftBlob, ftGraphic, ftOraBlob, ftOraClob:
begin
blob := TStringStream.Create('');
try
TBlobField(field).SaveToStream(blob);
childobj.S[field.FieldName] := EncodeString(blob.DataString); // base64 编码
finally
blob.Free;
end;
end;
end;
end;
end; // end for
dataset.Next;
end; // end while
Result := obj.ToString;
end;

procedure jsonToDataset(const json: string; dataset: TDataSet);
// {"data":[{"field1":value1,"field2":value2}]};
var
obj, childobj: TJsonObject;
i, j: Integer;
field: TField;
blob: TStringStream;
begin
if (dataset = nil) or (not dataset.Active) or (json = '{"result":"false"}') then
Exit;
obj := TJsonObject.Parse(json) as TJsonObject;
dataset.DisableControls;
try
for i := 0 to obj.A['data'].Count - 1 do
begin
dataset.Append;
childobj := obj.A['data'].O[i];
if childobj = nil then
continue;
for j := 0 to dataset.FieldCount - 1 do
begin
field := dataset.Fields[j];
if field = nil then
Continue;
case field.datatype of
ftBoolean:
field.AsBoolean := childobj.B[field.FieldName];
ftFloat, ftBCD, ftCurrency:
field.AsFloat := childobj.F[field.FieldName];
ftSmallint, ftInteger, ftWord, ftAutoInc:
field.AsInteger := childobj.I[field.FieldName];
ftString, ftFixedChar, ftMemo, ftWideString:
field.AsString :=UTF8ToString(rawbytestring( TNetEncoding.URL.Decode(childobj.S[field.FieldName]))); // 解码
ftTimeStamp, ftDate, ftTime, ftDateTime:
field.AsDateTime := childobj.D[field.FieldName];
ftLargeint:
TLargeintField(field).AsLargeInt := childobj.L[field.FieldName];
ftBytes, ftVarBytes, ftBlob, ftGraphic, ftOraBlob, ftOraClob:
begin
blob := TStringStream.Create(DecodeString(childobj.S[field.FieldName]));
try
TBlobField(field).LoadFromStream(blob);
finally
blob.Free;
end;
end;
end;
end;
dataset.Post;
end;
finally
dataset.EnableControls;
obj.free;
end;
end;

function datasetToJson(dataset: TDataSet): string;
// {"data":[{"field1":value1,"field2":value2}]};
var
i: Integer;
obj, childobj: TJsonObject;
field: TField;
blob: TStringStream;
begin
Result := '{"result":"false"}';
if (dataset = nil) or (not dataset.Active) then
Exit;
obj := TJsonObject.Create;
try
obj.A['data'];
dataset.First;
while not dataset.Eof do
begin
childobj := obj.A['data'].AddObject;
for i := 0 to dataset.FieldCount - 1 do
begin
field := dataset.Fields[i];
if field.IsNull then
childobj.S[field.FieldName] := ''
else
begin
case field.datatype of
ftBoolean:
childobj.B[field.FieldName] := field.AsBoolean;
ftSmallint, ftInteger, ftWord, ftAutoInc:
childobj.I[field.FieldName] := field.AsInteger;
ftLargeint:
childobj.L[field.FieldName] := TLargeintField(field).AsLargeInt;
ftCurrency, ftFloat, ftBCD:
childobj.F[field.FieldName] := field.AsFloat;
ftTimeStamp, ftDate, ftTime, ftDateTime:
childobj.D[field.FieldName] := field.AsDateTime;
ftString, ftFixedChar, ftMemo, ftWideString:
childobj.S[field.FieldName] := TNetEncoding.URL.Encode(string(UTF8Encode(field.AsString)));
ftBytes, ftVarBytes, ftBlob, ftGraphic, ftOraBlob, ftOraClob:
begin
blob := TStringStream.Create('');
try
TBlobField(field).SaveToStream(blob);
childobj.S[field.FieldName] := EncodeString(blob.DataString); // base64 编码
finally
blob.Free;
end;
end;
end;
end;
end; // end for
dataset.Next;
end; // end while
Result := obj.ToString;
finally
obj.Free;
end;
end;

end.

JsonDataObjects序列和还原的更多相关文章

  1. msgpack的数据序列和还原

    msgpack的数据序列和还原 msgpack不仅可以序列一些常规的数据类型的数据,比如:string.datetime.integer...... 还能序列olevariant.stream 这就非 ...

  2. QJSON封装好的序列和还原方法

    QJSON封装好的序列和还原方法 {*******************************************************}{ }{ QJSON与数据集互转 }{ }{ 版权所 ...

  3. MSGPACK序列和还原TFDParams

    MSGPACK序列和还原TFDParams unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, S ...

  4. 优秀的数据序列和还原类----TSimpleMsgPack

    优秀的数据序列和还原类----TSimpleMsgPack TSimpleMsgPack是D10天地弦的作品. 优点:至简,就一个单元文件实现,不需要引用其他单元. 缺点:不是标准的MSGPACK实现 ...

  5. cross socket和msgpack的数据序列和还原

    cross socket和msgpack的数据序列和还原 procedure TForm1.Button1Click(Sender: TObject); begin var pack: TSimple ...

  6. TynSerial流的序列(还原)

    TynSerial流的序列(还原) procedure TForm1.ToolButton18Click(Sender: TObject); var serial: TynSerial; ms, ms ...

  7. TynSerial基本数据类型序列(还原)

    TynSerial基本数据类型序列(还原) procedure TForm1.ToolButton17Click(Sender: TObject); var serial: TynSerial; be ...

  8. TynSerial序列(还原)TFDMemTable

    TynSerial序列(还原)TFDMemTable 1)TFDMemTable查询数据 procedure TForm1.Qrys(accountno, sql, sql2: string; Dat ...

  9. TynSerial图片序列(还原)

    TynSerial图片序列(还原) 笔者以生成图形验证码为例. function TForm1.VerifyCode(image: TImage): string; // 生成验证码和图像 var u ...

随机推荐

  1. Linq学习(一)

    与LINQ有关的语言特性 1.隐式类型 var 2.匿名类型 如:var obj = new {Guid.Empty, myTitle = "匿名类型", myOtherParam ...

  2. reinterpret_cast and const_cast

    reinterpret_cast reinterpret意为“重新解释” reinterpret_cast是C++中与C风格类型转换最接近的类型转换运算符.它让程序员能够将一种对象类型转换为另一种,不 ...

  3. nyoj 题目21 三个水杯

    三个水杯 时间限制:1000 ms  |  内存限制:65535 KB 难度:4   描述 给出三个水杯,大小不一,并且只有最大的水杯的水是装满的,其余两个为空杯子.三个水杯之间相互倒水,并且水杯没有 ...

  4. [bzoj2038] [2009国家集训队]小Z的袜子

    Description 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命-- 具体来说,小Z把这N只 ...

  5. 【普通の惨败】GDOI2015卖萌记

    前记:这次可真的全程卖萌了.... Day 0 早早坐上前往广州的火车,然后转车到韶关 然后就到了偏远郊区的(准)四星酒店 周围连路灯都没有,极其僻静极其荒凉 大家都极其安静地回到自己房间复习 这一天 ...

  6. POJ 3177 Redundant Paths 无向图边双联通基础题

    题意: 给一个无向图,保证任意两个点之间有两条完全不相同的路径 求至少加多少边才能实现 题解: 得先学会一波tarjan无向图 桥的定义是:删除这条边之后该图不联通 一条无向边(u,v)是桥,当且仅当 ...

  7. ZOJ Bizarre Routine 2013杭州网赛B题

    题目意思: 给定n, expect, a, b 要求你构造一组array[],存放一个1..n的排列,使的下面的程序能输出YES 题目所示代码: bool less_than(x, y) { T++; ...

  8. 转:Mysql explain

    转自:http://blog.csdn.net/zhuxineli/article/details/14455029(单纯学习而转) explain显示了MySQL如何使用索引来处理select语句以 ...

  9. Aspose.Cells 基础用法

    最近使用Aspose.Cells做Excel,在怎么添加批注和添加内部导航链接上耗费了一些时间,最后在官网上找到相关用法,记录一下. 代码不用过多介绍,看看即可明白. 测试代码下载 Workbook ...

  10. odp.net 读写oracle blob字段

    DEVELOPER: ODP.NET Serving Winning LOBs: http://www.oracle.com/technetwork/issue-archive/2005/05-nov ...