第四章 IRIS JSON数据类型

ObjectScript没有等同于JSON truefalsenull的不同常量,JSON也没有具有未定义值的数组元素的概念。本章讨论了这些不匹配,并描述了为处理这些不匹配而提供的工具。

  • 使用%GetTypeOf()查找值的数据类型
  • %Set()%Push()重写默认数据类型
  • 解析JSON空值和布尔值
  • 解析Null、空字符串和未分配的值

4.1 使用%GetTypeOf()查找值的数据类型

可以使用%GetTypeOf()方法获取动态实体成员的数据类型。动态对象属性或数组元素可以具有以下任意一种数据类型:

  • 对象数据类型:
    • array—动态数组引用
    • object-动态对象引用
    • oref-对不是动态实体的对象的引用
  • 文字值:
    • number-规范数值
    • string-字符串文本或计算为字符串文本的表达式
  • JSON文本:
    • boolean-JSON文本true或false
    • null-JSON文本null
  • 无数据类型:
    • unassigned-属性或元素存在,但没有赋值。

对对象使用%GetTypeOf:

​ 对对象使用此方法时,参数是属性的名称。例如:

   set dynobj={"prop1":123,"prop2":[7,8,9],"prop3":{"a":1,"b":2}}
   set iter = dynobj.%GetIterator()
   while iter.%GetNext(.name) {write !,"Datatype of "_name_" is "_(dynobj.%GetTypeOf(name))}

Datatype of prop1 is number
Datatype of prop2 is array
Datatype of prop3 is object

对数组使用%GetTypeOf:

​ 将此方法用于数组时,参数是元素的索引。下面的示例检查稀疏数组,其中元素2没有赋值。该示例使用for循环,因为%GetNext()将跳过未分配的元素:

   set dynarray = [12,34]
   set dynarray."3" = "final"
   write dynarray.%ToJSON()
[12,34,null,null,"final"]

   for index = 0:1:3 {write !,"Datatype of "_index_" is "_(dynarray.%GetTypeOf(index))}
Datatype of 0 is number
Datatype of 1 is number
Datatype of 2 is unassigned
Datatype of 3 is string

区分数组或对象和oref:

​ 动态实体的数据类型将是数组或对象。非动态实体的InterSystems IRIS对象的数据类型为oref。在下面的示例中,对象dyn的每个属性都是这三种数据类型之一。属性dynobject为类%DynamicObject,属性dyarray为%DynamicArray,而属性streamobj%Stream.GlobalCharacter

   set dyn={"dynobject":{"a":1,"b":2},"dynarray":[3,4],"streamobj":(##class(%Stream.GlobalCharacter).%New())}
   set iterator=dyn.%GetIterator()
   while iterator.%GetNext(.key,.val) { write !, "Datatype of "_key_" is: "_dyn.%GetTypeOf(key) }

Datatype of dynobject is: object
Datatype of dynarray is: array
Datatype of streamobj is: oref

4.2 用%Set()%Push()重写默认数据类

默认情况下,系统会自动将%Set()%Push()值参数解释为对象数据类型(对象、数组或oref)或ObjectScript文本数据类型(字符串或数字)。不能直接将JSON文本null、true或false作为值传递,因为参数被解释为ObjectScript文本或表达式。例如,以下代码引发错误,因为值true被解释为变量名:

   do o.%Set("prop3",true)

DO o.%Set("prop3",true)
^
<UNDEFINED> *true

ObjectScript使用""(空字符串)表示null,0表示布尔值false,非零数字表示布尔值true。为了解决这个问题,%Set()%Push()使用可选的第三个参数来指定值的数据类型。第三个参数可以是JSON布尔值或null。例如:

   write {}.%Set("a",(2-4)).%Set("b",0).%Set("c","").%ToJSON()
{"a":-2,"b":0,"c":""}

   write {}.%Set("a",(2-4),"boolean").%Set("b",0,"boolean").%Set("c","","null").%ToJSON()
{"a":true,"b":false,"c":null}

如果值可以解释为数字,则第三个参数也可以是字符串或数字:

   write [].%Push("023"_"04").%Push(5*5).%ToJSON()
["02304",25]

   write [].%Push(("023"_"04"),"number").%Push((5*5),"string").%ToJSON()
[2304,"25"]

4.3 解析JSON空值和布尔值

在JSON语法中,值true、false和null与值1、0和"“(空字符串)不同,但ObjectScript不做此区分。当从元素或属性中检索JSON值时,它们总是转换为与ObjectScript兼容的值。这意味着JSON true始终返回为1,false返回为0,null返回为”"。在大多数情况下,这将是所需的结果,因为返回值可以在ObjectScript表达式中使用,而无需首先将其从JSON格式转换。动态实体在内部保留原始JSON或ObjectScript值,因此如果需要,可以使用%GetTypeOf()来标识实际的数据类型。

在以下示例中,动态数组构造函数指定JSON true、false和null值、数值和字符串文字值以及ObjectScript动态表达式(其计算结果为ObjectScript布尔值1和0):

   set test = [true,1,(1=1),false,0,(1=2),"",null]
   write test.%ToJSON()
[true,1,1,false,0,0,"",null]

如上所述,构造函数中分配的值已保存在生成的动态数组中,并在序列化为JSON字符串时正确显示。

以下示例检索并显示数组值。正如预期的那样,JSON值true、false和null被转换为ObjectScript兼容的值1、0和“”:

   set iter = test.%GetIterator()
   while iter.%GetNext(.key,.val){write "/"_val_"/ "}
/1/ /1/ /1/ /0/ /0/ /0/ // //

此示例使用%GetNext(),但如果使用%get()%Pop()或点语法检索值,则会得到相同的结果。

必要时,可以使用%GetTypeOf()方法来发现值的原始数据类型。例如:

   set iter = test.%GetIterator()
   while iter.%GetNext(.key,.val) {write !,key_": /"_test.%Get(key)_"/ = "_test.%GetTypeOf(key)}
0: /1/ = boolean
1: /1/ = number
2: /1/ = number
3: /0/ = boolean
4: /0/ = number
5: /0/ = number
6: // = string
7: // = null

注:

动态对象中的数据类型

尽管本章重点介绍动态数组,但相同的数据类型转换适用于动态对象值。如果将动态数组测试替换为以下动态对象,本节中的示例将完全相同:

   set test = {"0":true,"1":1,"2":(1=1),"3":false,"4":0,"5":(1=2),"6":"","7":null}

除了这一行之外,不需要更改任何示例代码。此对象中的属性名是与原始数组的索引号相对应的数字字符串,因此即使输出也将相同。

4.4 解析Null、空字符串和未分配的值

尽管您可以为元素或属性分配JSON空值,但该值将始终返回为""(ObjectScript空字符串)。如果尝试获取未分配元素的值,也将返回空字符串。您可以使用%GetTypeOf()来识别每种情况下的实际数据类型。

此示例将测试包含JSON空值和空字符串的稀疏数组。尽管数组元素2没有赋值,但它将在JSON字符串中用null表示:

   set array = [null,""]
   do array.%Set(3,"last")
   write array.%ToJSON()
[null,"",null,"last"]

在大多数情况下,您可以使用%GetNext()来检索数组值,但本示例使用for循环来返回%GetNext()将跳过的未分配值。最后一个元素的索引编号为array.%Size()-1,但循环计数器故意设置为超过数组的末尾:

   for i=0:1:(array.%Size()) {write !,i_". value="""_array.%Get(i)_""" type="_array.%GetTypeOf(i)}
0. value="" type=null
1. value="" type=string
2. value="" type=unassigned
3. value="last" type=string
4. value="" type=unassigned

在此示例中,%Get()在四种不同的情况下返回一个空字符串:

  1. 元素0是JSON空值,%GetTypeOf()将其标识为数据类型null。
  2. 元素1是一个空字符串,它被标识为数据类型字符串。
  3. 元素2没有值,被标识为未分配的数据类型。
  4. 尽管元素3是数组中的最后一个元素,但该示例尝试为不存在的元素4获取数据类型,该元素也被标识为未分配的数据类型。有效的数组索引号将始终小于数组。%Size()

注:

null和未赋值之间的区别是当动态实体序列化为JSON字符串时不会保留的ObjectScript元数据。所有未分配的元素都将序列化为空值。有关详细信息,请参阅“了解稀疏数组和未分配值”。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值