Lazarus JSON 数据处理
在 Lazarus 中 JSON 格式的数据可以通过 fcl-json 来进行处理。fcl-json 是一个 json 实现,包括以下单元:
- fpjson:实现 TJsonData及其子级的基本单元,例如 TJsonObject
- jsonParser:实现 TJsonParser
- jsonConf:实现 TJsonConfig,它可以方便地从文件中读取/写入应用程序数据
- jsonScanner: json源词法分析器
今天,我们主要学习 fpjson、jsonParser 及 jsonConf 的使用。
1.使用 fpjson 与 jsonparser
通常情况下,我们使用 fpjson 与 jsonparser 就可以实现关于 JSON 数据处理的基本操作了。比如:将 JSON 格式的字符串解析为 JSON 对象,或者将 JSON 对象转换为 JSON 格式的字符串等。基本的 JSON 对象包括:
- TJSONData - JSON数据
- TJSONObject - JSON对象
- TJSONArray - JSON数组
示例:
uses
fpjson, jsonparser;
procedure JSONTest;
var
jData : TJSONData;
jObject : TJSONObject;
jArray : TJSONArray;
s : String;
begin
// 这仅仅是使用此API可以完成的工作的一个最小示例
// 通过字符串创建 JSON 数据
jData := GetJSON('{"Fld1" : "Hello", "Fld2" : 42, "Colors" : ["Red", "Green", "Blue"]}');
// 输出 JSON 字符串
s := jData.AsJSON;
// 输出格式化的 JSON 字符串
s := jData.FormatJSON;
// 将 JSON 数据转换为 JSON 对象
jObject := jData as TJSONObject;
// 获取其中的字段 Fld1 的值
s := jObject.Get('Fld1');
// 修改字段 Fld1 的值
jObject.Integers['Fld2'] := 123;
// 获取字段 Colors 数组的某个元素
s := jData.FindPath('Colors[1]').AsString;
// 添加一个新的元素
jObject.Add('Happy', True);
// 添加一个数组
jArray := TJSONArray.Create;
jArray.Add('North');
jArray.Add('South');
jArray.Add('East');
jArray.Add('West');
jObject.Add('Directions', jArray);
end;
注意:使用完 jData 后,有必要释放它。否则会造成内存泄漏。
遍历项目
示例:
uses
Classes, TypInfo, fpjson, jsonparser;
procedure JSONItems(Info: TStrings);
var
jData : TJSONData;
jItem : TJSONData;
i, j: Integer;
object_name, field_name, field_value, object_type, object_items: String;
begin
// 通过字符串创建 JSON 数据
jData := GetJSON('{"A":{"field1":0, "field2": false},"B":{"field1":0, "field2": false}}');
// 遍历元素
for i := 0 to jData.Count - 1 do
begin
jItem := jData.Items[i];
object_type := GetEnumName(TypeInfo(TJSONtype), Ord(jItem.JSONType));
object_name := TJSONObject(jData).Names[i];
WriteStr(object_items, jItem.Count);
Info.Append('object type: ' + object_type + '|object name: ' + object_name + '|number of fields: ' + object_items);
for j := 0 to jItem.Count - 1 do
begin
field_name := TJSONObject(jItem).Names[j];
field_value := jItem.FindPath(TJSONObject(jItem).Names[j]).AsString;
Info.Append(field_name + '|' + field_value);
end;
end;
jData.Free;
end;
2.使用 jsonConf
在 jsonConf 单元中,TJSONConfig 类可以用来对 JSON 数据进行文件操作,如:将 JSON 保存为文件,或者将 JSON 格式的文件内容加载到变量中。
示例:将窗口的属性写入到 JSON 文件中。
uses
jsonConf;
procedure SaveFormPos(AForm: TForm; const AFilename: string);
var
c: TJSONConfig;
begin
c:= TJSONConfig.Create(Nil);
try
//try/except to handle broken json file
try
c.Formatted:= true;
c.Filename:= AFilename;
except
exit;
end;
c.SetValue('/dialog/max', AForm.WindowState=wsMaximized);
if AForm.WindowState<>wsMaximized then
begin
c.SetValue('/dialog/posx', AForm.Left);
c.SetValue('/dialog/posy', AForm.Top);
c.SetValue('/dialog/sizex', AForm.Width);
c.SetValue('/dialog/sizey', AForm.Height);
end;
finally
c.Free;
end;
end;
示例:从文件中加载数据并对窗体属性进行赋值。
procedure LoadFormPos(AForm: TForm; const AFilename: string);
var
nLeft, nTop, nW, nH: Integer;
c: TJSONConfig;
begin
c:= TJSONConfig.Create(Nil);
try
//try/except to handle broken json file
try
c.Formatted:= true;
c.Filename:= AFilename;
except
exit;
end;
nLeft:= c.GetValue('/dialog/posx', AForm.Left);
nTop:= c.GetValue('/dialog/posy', AForm.Top);
nW:= c.GetValue('/dialog/sizex', AForm.Width);
nH:= c.GetValue('/dialog/sizey', AForm.Height);
AForm.SetBounds(nLeft, nTop, nW, nH);
if c.GetValue('/dialog/max', false) then
AForm.WindowState:= wsMaximized;
finally
c.Free;
end;
end;
示例:加载文件内容到 TStringList。
uses
jsonConf;
var
cfg: TJSONConfig;
List: TStringList;
path: string;
begin
List:= TStringList.Create;
cfg:= TJSONConfig.Create(nil);
try
//try/except to handle broken json file
try
cfg.Formatted:= true;
cfg.Filename:= AJsonFilename;
except
exit;
end;
cfg.GetValue('/mylist', List, '');
List.Add('some_value');
cfg.SetValue('/mylist', List);
finally
cfg.Free;
List.Free;
end;
3.浮点数处理
当 JSON 数据中包含浮点数时,如果将数据写入 JSON 文件,比如使用 FormatJSON() 方法使输出更可读。输出的浮点数的类似于:
"coordinates" : [
5.5978631048365003E+001,
2.2100000000000000E+002
]
这样的情况可以定义一个专门的类来处理,示例代码如下:
uses
fpjson,
jsonparser,
SysUtils;
type
TJSONFloat4Number = class(TJSONFloatNumber)
protected
function GetAsString: TJSONStringType; override;
end;
function TJSONFloat4Number.GetAsString: TJSONStringType;
var
F: TJSONFloat;
fs: TFormatSettings;
begin
fs := DefaultFormatSettings;
fs.DecimalSeparator := '.';
F := GetAsFloat;
Result := FormatFloat('0.0###############', F, fs); // format with your preferences
end;
测试代码:
procedure JSONTest;
var
jData: TJSONData;
begin
jData := GetJSON('{"coordinates": [5.5978631048365003E+001, 2.2100000000000000E+002]}');
writeln(jData.FormatJSON);
jData.Free;
end;
begin
SetJSONInstanceType(jitNumberFloat, TJSONFloat4Number);
JSONTest;
Readln;
end.