JSON 的崛起之路(上)-简介
JSON 的崛起之路(中)-“用错”的 AJAX,却成就了 JSON
JSON 的崛起之路(下)-常见的数据交换格式对比
在开发中处理数据交换时,JSON 因其简洁和通用性成为首选格式之一。对于使用 RAD Studio(尤其是 Delphi)的开发者而言,了解其内置的 JSON 处理能力至关重要。本文将带您快速入门,了解 RAD Studio 中两种核心 JSON 框架的区别、写法、读法以及近年来的重要改进。
本篇主要内容如下:
- JSON 框架
- JSON 框架之间的区别
- 编写 JSON 的三种方式
- 读取 JSON 的三种方式
- JSON 的处理与改进
RAD Studio 内置了丰富的 JSON 处理框架,提供了用于存储、解析、读取、写入和生成 JSON 格式数据的类与方法。
JSON 框架
RAD Studio 主要提供了两种不同的框架来处理 JSON 数据:
- JSON 对象框架:该框架通过创建临时对象来读写 JSON 数据。
- JSON 读写器框架:该框架支持直接对流进行 JSON 数据的读写,无需创建临时对象。
JSON 对象框架
JSON 对象框架在解析或生成 JSON 数据时,需要先创建一个临时的内存对象(如 TJSONObject、TJSONArray 或 TJSONString),然后再进行读写操作。这种方式直观,便于理解和操作 JSON 的树形结构。
详见后续文章:RAD Studio JSON(2)之JSON 对象框架
JSON 读写器框架
JSON 读写器框架允许直接向数据流中读写 JSON,而无需创建临时对象。因此,该框架在性能和内存占用方面更具优势,尤其适合处理大体积的 JSON 数据。
此外,与 JSON 对象框架不同,读写器框架还支持 BSON 格式。
JSON 框架之间的区别
在处理 JSON 数据时,你可以根据项目需求选择任一框架。下表列出了两种框架的主要差异,这份对比也是理解如何选择框架的绝佳 技术文档 素材:
| 特性 |
JSON 对象框架 |
JSON 读写器框架 |
| 使用方式 |
更便于读取 JSON 结构,支持对模型树进行遍历和修改 |
以流式顺序方式读写 JSON,降低内存消耗 |
| 性能 |
相对较低(需创建中间对象) |
更高(无需中间对象) |
| 功能扩展 |
不支持 BSON |
支持 BSON,且具备良好的可扩展性 |
以下三段代码展示了使用不同框架编写相同 JSON 数据的方式:
编写 JSON 的三种方式
1. JSON 对象框架
JSONColor := TJSONObject.Create;
JSONColor.AddPair('name', 'red');
JSONColor.AddPair('hex', '#f00');
JSONArray := TJSONArray.Create;
JSONArray.Add(JSONColor);
JSONObject := TJSONObject.Create;
JSONObject.AddPair('colors', JSONArray);
2. JSON 读写器框架(TJsonWriter)
Writer.WriteStartObject;
Writer.WritePropertyName('colors');
Writer.WriteStartArray;
Writer.WriteStartObject;
Writer.WritePropertyName('name');
Writer.WriteValue('red');
Writer.WritePropertyName('hex');
Writer.WriteValue('#f00');
Writer.WriteEndObject;
Writer.WriteEndArray;
Writer.WriteEndObject;
3. JSON 读写器框架(TJSONObjectBuilder)
Builder := TJSONObjectBuilder.Create(Writer);
Builder
.BeginObject
.BeginArray('colors')
.BeginObject
.Add('name', 'red')
.Add('hex', '#f00')
.EndObject
.EndArray
.EndObject;
上述三种方式均生成如下 JSON:
{
"colors":[
{
"name":"red",
"hex":"#f00"
}
]
}
读取 JSON 的三种方式
1. JSON 对象框架
JSONValue := TJSONObject.ParseJSONValue('{"colors":[{"name":"red", "hex":"#f00"}]}');
Memo1.Lines.Add('READER:');
if JSONValue is TJSONArray then
//...
else if JSONValue is TJSONObject then
begin
Memo1.Lines.Add('colors');
Memo1.Lines.Add('name: ' + JSONValue.GetValue<string>('colors[0].name'));
Memo1.Lines.Add('hex: ' + JSONValue.GetValue<string>('colors[0].hex'));
end;
2. JSON 读写器框架(TJsonReader)
LStringReader := TStringReader.Create('{"colors":[{"name":"red", "hex":"#f00"}]}');
LJsonTextReader := TJsonTextReader.Create(LStringReader);
while LJsonTextReader.Read do
case LJsonTextReader.TokenType of
TJsonToken.PropertyName:
Memo1.Lines.Add(LJsonTextReader.Value.AsString);
TJsonToken.String:
Memo1.Lines[Memo1.Lines.Count - 1] := Memo1.Lines[Memo1.Lines.Count - 1] + ': ' + LJsonTextReader.Value.AsString;
end;
3. JSON 读写器框架(TJSONIterator)
LStringReader := TStringReader.Create('{"colors":[{"name":"red", "hex":"#f00"}]}');
LJsonTextReader := TJsonTextReader.Create(LStringReader);
LIterator := TJSONIterator.Create(LJsonTextReader);
LIterator.Recurse;
LIterator.Next;
Memo1.Lines.Add(LIterator.Key);
LIterator.Recurse;
LIterator.Recurse;
LIterator.Next;
LIterator.Recurse;
LIterator.Next;
Memo1.Lines.Add(LIterator.Key + ': ' + LIterator.AsString);
LIterator.Next;
Memo1.Lines.Add(LIterator.Key + ': ' + LIterator.AsString);
以上三种方式都会在 TMemo 控件中输出如下内容:
colors
name: red
hex: #f00
JSON 的处理与改进
近年来,RAD Studio 中的 JSON 处理框架也在持续优化,主要体现在以下几个方面:
- 提升 JSON 代码的准确性:无论是
TJSONValue 及其派生类生成的 JSON,还是 JSON 解析过程,都进行了优化。
- 性能增强:引入了新的
TAsciiStreamWriter 类,与 TJsonTextWriter 配合使用,可显著提升 JSON 字符串生成的性能(减少字符编码转换)。
- 美化输出支持:新增
TJSONAncestor.Format(Indentation: Integer = 4) 方法,用于生成带缩进的“美化”JSON 输出。原有的 TJSON.Format 方法已弃用。
- 标准化输出:
TJSONAncestor.ToJSON 现在始终生成符合标准的 JSON 字符串;
TJSONAncestor.ToString 则生成类似 JSON 的字符串,但不会将非 ASCII 字符转义为 \uNNNN 形式。
- 增强错误处理机制:
- 新增
TJSONObject.TJSONParseOption.RaiseExc 选项,用于控制 ParseJSONValue 方法在遇到无效 JSON 时是抛出 EJSONParseException 异常,还是返回 nil(旧有行为)。
- 若启用异常模式,
ParseJSONValue 将返回详细的错误位置信息,并抛出新的 System.JSON.EJSONParseException 异常(包含 Path、Offset、Line 和 Position 属性)。
- 此外,
ParseJSONValue 方法新增第三个参数 RaiseExc,可在调用时临时覆盖全局设置,强制在解析出错时抛出异常。
总结来说,掌握 RAD Studio 中这两种 JSON 处理框架的差异和适用场景,能帮助你在实际开发中做出更优的技术选型,无论是构建高性能的 后端 & 架构 服务,还是处理日常的数据交换任务。希望这篇入门指南能为你打下扎实的基础。如果你想了解更多类似的深度技术解析和实践经验,欢迎访问 云栈社区 与其他开发者交流探讨。