-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathService.JSONUtils.pas
More file actions
120 lines (105 loc) · 3.02 KB
/
Copy pathService.JSONUtils.pas
File metadata and controls
120 lines (105 loc) · 3.02 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
unit Service.JSONUtils;
interface
uses
System.JSON,
System.Rtti,
System.SysUtils,
System.TypInfo,
System.Variants,
REST.JSON,
API.Types.Optional;
type
TJSONUtils = class
public
class function Serialize(const AObject: TObject): string; static;
class function Deserialize<T: class, constructor>(const AJson: string): T; static;
end;
implementation
{ TJSONUtils }
class function TJSONUtils.Serialize(const AObject: TObject): string;
var
ctx: TRttiContext;
rType: TRttiType;
prop: TRttiProperty;
val: TValue;
JSON: TJSONObject;
pair: TJSONPair;
optVal: Variant;
tmpInt: TOptional<Integer>;
tmpStr: TOptional<string>;
tmpDbl: TOptional<Double>;
tmpBool: TOptional<Boolean>;
isOptional: Boolean;
begin
JSON := TJSONObject.Create;
ctx := TRttiContext.Create;
try
rType := ctx.GetType(AObject.ClassType);
for prop in rType.GetProperties do
begin
if not prop.IsReadable then
Continue;
val := prop.GetValue(AObject);
isOptional := False;
if val.TryAsType < TOptional < Integer >> (tmpInt) then
begin
optVal := tmpInt.ValueOrNull;
isOptional := True;
end
else if val.TryAsType < TOptional < string >> (tmpStr) then
begin
optVal := tmpStr.ValueOrNull;
isOptional := True;
end
else if val.TryAsType < TOptional < Double >> (tmpDbl) then
begin
optVal := tmpDbl.ValueOrNull;
isOptional := True;
end
else if val.TryAsType < TOptional < Boolean >> (tmpBool) then
begin
optVal := tmpBool.ValueOrNull;
isOptional := True;
end;
if isOptional then
begin
if VarIsNull(optVal) then
pair := TJSONPair.Create(prop.Name, TJSONNull.Create)
else if VarIsStr(optVal) then
pair := TJSONPair.Create(prop.Name, TJSONString.Create(optVal))
else if VarIsNumeric(optVal) then
pair := TJSONPair.Create(prop.Name, TJSONNumber.Create(string(optVal)))
else if VarType(optVal) = varBoolean then
pair := TJSONPair.Create(prop.Name, TJSONBool.Create(optVal))
else
Continue;
JSON.AddPair(pair);
Continue;
end;
// Propriedades comuns
case val.Kind of
tkInteger:
JSON.AddPair(prop.Name, TJSONNumber.Create(val.AsInteger));
tkFloat:
JSON.AddPair(prop.Name, TJSONNumber.Create(FloatToStr(val.AsExtended, TFormatSettings.Invariant)));
// inclui TDateTime
tkString, tkUString, tkWString:
JSON.AddPair(prop.Name, TJSONString.Create(val.AsString));
tkEnumeration:
if val.TypeInfo = TypeInfo(Boolean) then
JSON.AddPair(prop.Name, TJSONBool.Create(val.AsBoolean))
else
JSON.AddPair(prop.Name, TJSONString.Create(val.ToString));
end;
end;
Result := JSON.ToJSON;
finally
ctx.Free;
JSON.Free;
end;
end;
class function TJSONUtils.Deserialize<T>(const AJson: string): T;
begin
Result := TJson.JsonToObject<T>(AJson);
end;
end.