写在前面
为了与大家保持一个愉快的沟通,以及便于描述方便,本文做了一些术语简写,如下:
尽量不讲废话
以总结的方式编写
dynEnt
:动态实体dynObj
:动态对象dynAry
:动态数组textConstructor
( 文本构造器):文字 JSON 构造函数{}
和[]
jsonStr
:文本 JSON 字符串
*
:表示重点掌握-
:废话可忽略spaAry
(稀疏数组):有些元素没有值JSON Adaptor
:json 适配器1. 导出和导入
JSON 适配器
是一种将 ObjectScript
对象(已注册、串行或持久)映射到 JSON 文本或动态实体的方法.
要从 JSON 序列化到 JSON 的任何类都需要子类%JSON.Adaptor
,其中包括以下方法:
%JSONExport()
将启用 JSON 的类序列化为 JSON 文档,并将其写入当前设备。
%JSONExportToStream()
将启用 JSON 的类序列化为 JSON 文档,并将其写入流。
%JSONExportToString()
将启用 JSON 的类序列化为 JSON 文档,并将其作为字符串返回。
%JSONImport()
将 JSON 作为字符串或流导入,或者作为%DynamicAbstractObject
,并返回已启用 JSON 的类的实例。
为了演示这些方法,本节中的示例将使用以下两个类:
Class Model.Event Extends (%Persistent, %JSON.Adaptor)
{
Property Name As %String;
Property Location As Model.Location;
}
和
Class Model.Location Extends (%Persistent, %JSON.Adaptor)
{
Property City As %String;
Property Country As %String;
}
如您所见,我们有一个持久事件类,它链接到一个位置。这两个类都继承自%JSON.Adaptor
.这使我们能够填充对象图并将其直接导出为 JSON 字符串。
set event = ##class(Model.Event).%New()
set event.Name = "Global Summit"
set location = ##class(Model.Location).%New()
set location.Country = "United States of America"
set event.Location = location
do event.%JSONExport()
此代码显示以下 JSON 字符串:
{"Name":"Global Summit","Location":{"City":"Boston","Country":"United States of America"}}
您可以使用 %JSONExportToString()
而不是 %JSONExport()
将 JSON 字符串分配给变量jsonEvent
:
do event.%JSONExportToString(.jsonEvent)
最后,您可以反转该过程,并将 JSON 字符串转换回具有 %JSONImport()
的对象。此示例采用上一示例中的字符串变量 jsonEvent
,并将其转换回 Model.Event
对象:
set eventTwo = ##class(Model.Event).%New()
do eventTwo.%JSONImport(jsonEvent)
write eventTwo.Name,!,eventTwo.Location.City
Global Summit
Boston
导入和导出都适用于任意嵌套的结构。
2. 使用参数进行映射
您可以通过设置相应的参数来指定每个单独属性的映射逻辑。(如果您熟悉%XML.Adaptor
,这是一个类似的过程)。
我们可以通过指定属性参数来更改 Model.Event 类
(在上一节中定义)的映射:
Class Model.Event Extends (%Persistent, %JSON.Adaptor)
{
Property Name As %String(%JSONFIELDNAME = "eventName");
Property Location As Model.Location(%JSONINCLUDE = "INPUTONLY");
}
此映射引入了两个更改:
Name
将映射到名为 eventName
的 JSON 字段。%JSONImport()
仍将将 Location 属性用作输入,但 %JSONExport()
和其他导出方法将忽略该属性。以前,在未修改的 Model.Event
类的实例上调用了 %JSONExport()
,并返回了以下 JSON 字符串:
{"Name":"Global Summit","Location":{"City":"Boston","Country":"United States of America"}}
如果我们在重新映射的 Model.Event
的实例上调用 %JSONExport()
(使用相同的属性值),将返回以下字符串:
{"eventName":"Global Summit"}
有各种参数可用于调整映射:
%JSONFIELDNAME
(仅限属性)设置要用作 JSON 内容中的字段名称的字符串(默认情况下,值是属性名称)。
%JSONIGNOREINVALIDFIELD
控制 JSON 输入中意外字段的处理。
%JSONIGNORENULL
允许开发人员覆盖字符串属性的空字符串的默认处理。
%JSONINCLUDE
(仅限属性)指定此属性是包含在 JSON 输出中还是输入中(有效值为“inout”(默认值)、“outputonly”、“inputOnly”或“none”)。
%JSONNULL
指定如何存储字符串属性的空字符串。
%JSONREFERENCE
指定如何投影对 JSON 字段的对象引用。选项包括“OBJECT
”(默认值)、“ID”、“OID”和“GUID”。
3. 使用 XData 映射块
您可以在特殊的 XData
映射块中指定映射,并在调用导入或导出方法时应用映射
,而不是在属性级别设置映射参数
。
下面的代码定义了前两节中使用的 Model.Event 类的另一个版本。在此版本中,未指定任何属性参数,但我们定义了一个名为 OnlyLowercaseTopLevel
的 XData
映射块,该块指定与以前版本中的属性相同的参数设置:
Class Model.Event Extends (%Persistent, %JSON.Adaptor)
{
Property Name As %String;
Property Location As Model.Location;
XData OnlyLowercaseTopLevel
{
<Mapping xmlns="http://www.intersystems.com/jsonmapping">
<Property Name="Name" FieldName="eventName"/>
<Property Name="Location" Include="INPUTONLY"/>
</Mapping>
}
}
有一个重要的区别:XData
块中的 JSON 映射不会更改默认行为
,但您可以通过在导入和导出方法的可选 %mappingName
参数中指定块名称来应用它们。例如:
do event.%JSONExport("OnlyLowercaseTopLevel")
{"eventName":"Global Summit"}
就好像参数已在属性定义中指定一样
. 如果没有具有提供名称的 XData 块,则将使用默认映射。使用此方法,您可以配置多个映射并单独引用每个调用所需的映射,从而授予您更多的控制权,同时使您的映射更加灵活和可重用。
4. 定义 XData 映射块
启用 JSON 的类可以定义任意数量的附加映射。每个映射都定义在以下形式的单独 XData 块中:
XData {MappingName}
{
<Mapping {ClassAttribute}="value" [...] xmlns="http://www.intersystems.com/jsonmapping".>
<{Property Name}="PropertyName" {PropertyAttribute}="value" [...] />
[... more Property elements]
</Mapping>
}
其中 {MappingName}、{ClassAttribute}、{Property Name} 和 {PropertyAttribute} 定义如下:
MappingName
供 %JSONREFERENCE
参数或引用属性使用的映射的名称。
ClassAttribute
指定映射的类参数。可以定义以下类属性:
Mapping ― 要应用的 XData 映射块的名称。
IgnoreInvalidField — 指定类参数 %JSONIGNOREINVALIDFIELD。
Null — 指定类参数 %JSONNULL。
IgnoreNull — 指定类参数 %JSONIGNORENULL。
Reference ― 指定类参数 %JSONREFERENCE。
PropertyName
要映射的属性的名称。
PropertyAttribute
指定映射的属性参数。可以定义以下属性特性:
FieldName — 指定属性参数 %JSONFIELDNAME(默认情况下与属性名称相同)。
Include — 指定属性参数 %JSONINCLUDE(有效值为“inout”(默认值)、“outputonly”、“inputOnly”或“none”)。
Mapping ― 要应用于对象属性的映射定义的名称。
Null — 覆盖类参数 %JSONNULL。
IgnoreNull — 覆盖类参数 %JSONIGNORENULL。
Reference — 覆盖类参数 %JSONREFERENCE。
5. 格式化 JSON
%JSON.Formatter
是一个具有非常简单接口的类,允许您将动态对象和数组以及JSON字符串格式化为更易于阅读的表示形式。所有方法都是实例方法,因此您始终从检索实例开始:
set formatter = ##class(%JSON.Formatter).%New()
Format()
方法采用动态实体或 JSON 字符串。下面是一个使用动态对象的简单示例:
dynObj = {"type":"string"}
do formatter.Format(dynObj)
//显示
{
"type":"string"
}
格式方法可以将输出定向到当前设备、字符串或流:
Format()
使用指定的缩进格式化 JSON 文档,并将其写入当前设备。
FormatToStream()
使用指定的缩进设置 JSON 文档的格式,并将其写入流。
FormatToString()
使用指定的缩进设置 JSON 文档的格式并将其写入字符串,或者将启用 JSON 的类序列化为 JSON 文档并将其作为字符串返回。
此外,以下属性可用于控制缩进和换行符:
Indent 指定是否应缩进 JSON 输出
IndentChars 指定要用于每个缩进级别的字符序列(默认为每个级别一个空格)。
LineTerminator 指定在缩进时终止每一行的字符序列。