写在前面
尽量不讲废话
以总结的方式编写
1. 在 ObjectScript 中使用 JSON(吹牛的话)
各位,有些废话还是要讲,根据官方文档介绍如下:
InterSystems ObjectScript
语法包括了对 JSON支持。其提供了快速、简单、强大的功能,您可以像处理对象或表一样轻松地使用 JSON
数据结构。
借助 JSON
的 ObjectScript
语法,您可以使用标准的 ObjectScript
赋值语句而不是方法调用在运行时创建和更改动态实体。对象属性和数组元素的值可以指定为 JSON字符串文本
或 ObjectScript 动态表达式
。
两个类:%Library.DynamicObject
和 %Library.DynamicArray
,提供了一种简单、高效的方式来封装和使用标准 JSON 数据结构。这两个类的实例称为动态实体(dynamic entities)
,本文以dynEnt
简称。
dynEnt
用于 JSON 序列化
(动态实体和规范 JSON 格式之间的转换)、迭代、数据类型、创建/读取/更新/删除操作等。
2. 约定(保持愉快的沟通)
为了与大家保持一个愉快的沟通,以及便于描述方便,本文做了一些术语简写,如下:
dynEnt
:动态实体textConstructor
( 文本构造器):文字 JSON 构造函数{}
和[]
jsonStr
:文本 JSON 字符串
*
:表示重点掌握3. 创建dynEnt(*)
您可以动态的创建dynEnt
,即在运行时创建(注意:%Library.DynamicObject
可以简写为%DynamicObject
,可以参考 IRIS 编程方向指南):
set dynObject1 = ##class(%DynamicObject).%New()
set dynObject1.SomeNumber = 42
set dynObject1.SomeString = "a string"
set dynObject1.SomeArray = ##class(%DynamicArray).%New()
set dynObject1.SomeArray."0" = "an array element"
set dynObject1.SomeArray."1" = 123
还可以通过分配jsonStr
来创建dynEnt
。textConstructor
可用于代替 %New()
构造函数。
例如,您可以使用设置 x=[]
而不是设置 x = ##class(%DynamicArray.%New()
创建一个动态数组。与 %New()
不同,textConstructor
还可以采用指定属性或元素的jsonStr
。这意味着您可以使用以下简单的赋值语句创建与上一示例3.1
中的 dynObject1 相同的对象:
set dynObject2 = {"SomeNumber":42,"SomeString":"a string"}
set dynObject2.SomeArray = ["an array element",123]
为了证明 dynObject1
和 dynObject2
是相同的,我们可以将它们显示为由 %ToJSON()
方法返回的序列化
JSON 字符串:
write "object 1: "_dynObject1.%ToJSON(),!,"object 2: "_dynObject2.%ToJSON()
object 1: {"SomeNumber":42,"SomeString":"a string","SomeArray":["an array element",123]}
object 2: {"SomeNumber":42,"SomeString":"a string","SomeArray":["an array element",123]}
4. 特殊用法说明(*)
textConstructor
中包含的文本必须使用有效的 JSON
语法,但有一个例外。对于元素或属性的值,可以使用括在括号中的ObjectScript
表达式,而不是 JSON 文本。此 ObjectScript
动态表达式,将在运行时计算并转换为有效的 JSON 值。底下示例中的动态表达式包括对 $ZDATE 函数的调用:
set dynObj = { "Date":($ZD($H,3)) }
序列化
:将dynEnt
转换成规范的jsonStr
动态实体具有序列化方法,允许它们在 JSON 字符串之间转换。在下面的示例中,textConstructor
用于创建dynEnt
,并调用该对象的 %ToJSON()
方法以将其序列化为 myJSONstring
:
set myJSONstring = {"aNumber":(21*2),"aDate":($ZD($H,3)),"anArray":["string",123]}.%ToJSON()
反序列化
:将规范jsonStr
转换成dynEnt
类方法 %FromJSON()
可以从任何源获取有效的 jsonStr
,并将其转换为 dynEnt
。下面的代码将 myJSONstring
反序列化为动态对象 myObject
,并使用 %ToJSON()
来显示它:
set myObject = ##class(%DynamicAbstractObject).%FromJSON(myJSONstring)
write myObject.%ToJSON()
{"aNumber":42,"aDate":"2016-08-29","anArray":["string",123]}
可以链接某些dynEnt
方法。例如:底下案例创建一个包含两个元素的动态数组,然后链接 %Push()
方法以将另外三个元素添加到数组的末尾。对 %ToJSON()
的最终链接调用将显示序列化字符串:
set dynArray = ["a","b"]
write dynArray.%Push(12).%Push({"a":1,"b":2}).%Push("final").%ToJSON()
["a","b",12,{"a":1,"b":2},"final"]
还提供了其他方法,用于迭代和获取元素的数据类型。此示例创建两个 JSON 字符串,将其中一个字符串反序列化为 dynEntity
,然后获取 dynEntity
的迭代器:
set arrayStr = [12,"some string",[1,2]].%ToJSON()
set objectStr = {"a":12,"b":"some string","c":{"x":1,"y":2}}.%ToJSON()
set dynEntity = {}.%FromJSON(objectStr)
set itr = dynEntity.%GetIterator()
对于 while
循环的每次迭代,%GetNext()
将返回 key 中的属性名称或数组索引以及 val 中的成员值。%GetTypeOf()
的返回值是一个字符串,指示值的数据类型:
while itr.%GetNext(.key,.val) {write !,key_": "_"/"_val_"/, type: "_dynEntity.%GetTypeOf(key)}
a: /12/, type: number
b: /some string/, type: string
c: /1@%Library.DynamicObject/, type: object
5. dynEnt 方法介绍(有个大体印象)
这段其实是也是一段废话,大家可看可不看,有个大体印象即可。根据官网介绍如下:
动态实体方法可以分为以下几类:
创建、读取、更新、删除
%Set()
可以更改现有动态实体成员(属性或元素)的值,也可以创建新成员并向其赋值。%Remove()
删除现有成员。%Get()
检索成员的值。迭代与数组
%GetIterator()
返回一个迭代器,其中包含指向动态实体的每个成员的指针%GetNext()
返回由迭代器标识的成员的键和值,并将游标前进到下一个成员。%Size()
返回成员数(包括数组中未赋值的元素)。%IsDefined()
测试成员是否具有分配的值。堆栈函数
%Push()
将新元素添加到动态数组的末尾。%Pop()
删除数组的最后一个元素并返回其值。这些方法不可用于dynEnt
,因为对象属性未按可预测的顺序存储。JSON 序列化和反序列化
%FromJSON()
将 JSON 字符串转换为动态实体。%ToJSON()
将动态实体序列化为规范的 JSON 字符串.数据类型信息
%GetTypeOf()
返回一个字符串,指示指定成员值的数据类型。%Set()
和 %Push()
提供可选的第三个参数来显式指定值的数据类型。