JSON Adaptor是一种将ObjectScript对象(注册的、串行的或持久的)映射到JSON文本或动态实体的方法。本章涵盖以下主题:
- 导出和导入-引入启用JSON的对象,并演示
%JSON.Adaptor
导入和导出方法。 - 参数映射-描述控制对象属性如何转换为JSON字段的属性参数。
- 使用XData映射块-描述了将多个参数映射应用于单个类的方法。
- 格式化JSON-演示如何使用
%JSON.Formatter
格式化JSON字符串。
6.1 导出和导入
要从JSON序列化或从JSON序列化的任何类都需要子类%JSON.Adaptor
,包括以下方法:
%JSONExport()
将启用JSON的类序列化为JSON文档,并将其写入当前设备。%JSONExportToStream()
将启用JSON的类序列化为JSON文档并将其写入流。%JSONExportToString()
将启用JSON的类序列化为JSON文档,并将其作为字符串返回。%JSONImport()
将JSON作为字符串或流导入,或导入%DynamicAbstractObject
的子类,并返回启用JSON的类的实例。
为了演示这些方法,本节中的示例将使用以下两个类:
(1)支持JSON的类Model.Event
和Model.Location
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字符串。
(2)将对象导出为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字符串分配给变量:
do event.%JSONExportToString(.jsonEvent)
最后,可以使用%JSONImport()
将JSON字符串转换回对象。此示例从上一示例中获取字符串变量jsonEvent
,并将其转换回Model.Event
对象:
(3)将JSON字符串导入对象
set eventTwo = ##class(Model.Event).%New()
do eventTwo.%JSONImport(jsonEvent)
write eventTwo.Name,!,eventTwo.Location.City
Global Summit
Boston
导入和导出都适用于任意嵌套的结构。
6.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字段。
- Location属性仍将被
%JSONImport()
用作输入,但%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”。
有关详细信息,请参阅本章后面的参考部分“%JSON.Adaptor
类和属性参数”。
6.3 使用XData映射块
您可以在特殊的XData mapping块中指定映射,并在调用导入或导出方法时应用映射,而不是在属性级别上设置映射参数。
下面的代码定义了前两节中使用的Model.Event
类的另一个版本。在此版本中,没有指定属性参数,但我们定义了一个名为OnlyLowercaseTopLevel
的XData Mapping块,该块指定了与前一版本中的属性相同的参数设置:
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块,则将使用默认映射。使用这种方法,您可以配置多个映射,并单独引用每个调用所需的映射,从而在使映射更灵活和可重用的同时授予您更多的控制权。
6.3.1 定义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
参数或Reference属性使用的映射的名称。 - ClassAttribute:指定映射的类参数。可以定义以下类属性:
- Mapping-要应用的XData映射块的名称。
- IgnoreInvalidField-指定类参数
%JSONIGNOREINVALIDFIELD
。 - Null-指定类参数
%JSONNULL
。 - IgnoreNull-指定类参数
%JSONIGNORENNULL
。 - Reference-指定类参数
%JSONREFERENCE
。
- PropertyName:正在映射的属性的名称。
- PropertyAttribute:指定映射的属性参数。可以定义以下属性:
- FieldName-指定属性参数
%JSONFIELDNAME
(默认情况下与属性名称相同)。 - Include-指定属性参数
%JSONINCLUDE
(有效值为“inout”(默认值)、“outputly”、“inputOnly”或“none”)。 - Mapping-要应用于对象属性的映射定义的名称。
- Null-重写类参数
%JSONNULL
。 - IgnoreNull-重写类参数
%JSONIGNORENNULL
。 - Reference-重写类参数
%JSONREFERENCE
。
- FieldName-指定属性参数
6.4 格式化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
指定缩进时要终止每行的字符序列。