SPL:读写 JSON 数据

JSON是一种容易理解的结构化数据格式,它经常以一个大字符串的形式在各种计算机语言中传递信息,SPL语言提供了json()函数加载/生成JSON,加载成序表、序列对象后,就方便做计算了。

加载JSON数据

JSON中有数组、对象、数值、字符串、布尔值(truefalse)以及表示空值的nullSPLJSON的对象及数据类型能比较好的对应起来。

基本数据类型

JSON里其它基本数据类型在SPL中都能直接对应上,A1中的定义了一个JSON字符串(SPL单元格中,用单引号开头定义字符串),各种类型的数据组成一个JSON数组:


A

1

'["v1",66,true,false,null]

2

=json(A1)

..

JSON中没有专门的日期时间类型,传递日期时间数据时,可能是任意格式的格式化字符串,或数值类型的毫秒数:


A

1

'["string","2021-01-02","2021/01/03   12:15",1632627573336,66]

2

=json(A1)

..

SPL中需要日期时间类型时,可以把加载进来的格式化字符串、数值用date()datetime()等函数进行转换:


A

3

=[date(A2(2)),   datetime(A2(3),"yyyy/MM/dd HH:mm"), date(A2(4))]

 

数组

上例中各种类型数据是放在一个JSON数组中,如下A1再定一个等差数列的JSON数组


A

1

'[11,13,15,17]

2

=json(A1)

..

对象

如下A1是一个JSON对象:


A

1

'{"n1":"v1","n2":"v2","n3":"v3"}

2

=json(A1)

它加载成了一个单行的序表对象:

..

对象数组

很自然的,多个JSON对象组成一个数组后,就会加载成一个多行的序表对象:


A

1

'[{"n1":"v1","n2":"v2","n3":"v3"},   {n1:"v4",n2:"v5",n3:"v6"}, {"n1":"v7","n2":"v8","n3":"v9"}]

2

=json(A1)

另外,注意第二行的属性名没有双引号,这不符合JSON规范,但没按错误处理,也能正常解析出属性名:

..

 

不同结构对象数组

JSON数组中的多个对象,可能是异构的,第一个对象里没有n3属性,第二个对象里没有n1属性,第三个对象里没有n2属性:


A

1

'[{n1:"v1",n2:"v2"},{n2:"v5",n3:"v6"},{n1:"v7",n3:"v9"}]

2

=json@t(A1)

这种情况转换成序表时,会以所有JSON对象属性的合集为结构。JSON对象中缺失的值补为null,这样规范处理后,有利于后续计算。

..

嵌套数组及对象

JSON数组中的元素不限制数据类型,甚至可以是嵌套的数组、对象:


A

1

'[[1,2,3],{"n1":"v1","n2":"v2","n3":"v3"},"v1",66,true,null]

2

=json(A1)

序列同样也支持混合类型,第一个元素同样是序列,第二个元素是序表:

..

 

同理,JSON对象中的属性值,同样也可以嵌套数组、对象:


A

1

'{"n1":"v1","n2":[1,2,3],"n3":{"n31":"v31","n32":"v32","n33":"v33"}}

2

=json(A1)

..

数组、对象灵活嵌套后,形成多级结构化数据,JSONSPL都容易表达它们。

生成JSON字符串

加载的反向操作是生成JSON字符串,SPL中仍然用json()函数实现它,A2中把A1JSON字符串加载成SPL对象;A3中把A2SPL对象再转换回JSON字符串,json()函数判断传入参数的类型,会自动的选择正确的转换动作(传入JSON字符串时,转换成SPL对象;传入SPL对象时,转换成JSON字符串)


A

1

'[[1,2,3],{"n1":"v1","n2":"v2","n3":"v3"},"v1",66,true,null]

2

=json(A1)

3

=json(A2)

执行后,观察A3的值,能看到是和A1一样的JSON字符串:

[[1,2,3],{"n1":"v1","n2":"v2","n3":"v3"},"v1",66,true,null]

 

下面看生成JSON字符串时,SPL对象与JSON对象的对应关系。

基本数据类型


A

1

=["str",22,true,false,null,date(2021,9,18)]

2

=json(A1)

A1生成的SPL序列中,除了JSON支持的基本数据类型外,最后还有一个日期类型,转成JSON字符串时,它会被格式化成字符串类型:

..

 

数组

A1生成一个SPL序列,A2json()函数把它生成JSON字符串


A

1

=["a","b","c"]

2

=json(A1)

..

..

对象

A1创建了以n1n2n3为结构的空序表,A2A1中插入两条数据


A

1

=create(n1,n2,n3)

2

>A1.insert(0,"v1","v2","v3"),A1.insert(0,"v4","v5","v6")

3

=json(A1(2))

A1中的每一条记录对应一个JSON对象,A3中把第二条记录转换成JSON字符串

..

 

对象数组

SPL序列、序表写出时,会转成JSON数组,以上一节的序表为例,A3中把整个序表写出,最终结果是JSON对象数组


A

1

=create(n1,n2,n3)

2

>A1.insert(0,"v1","v2","v3"),A1.insert(0,"v4","v5","v6")

3

=json(A1)

 

..

嵌套数组及对象


A

1

=create(n1,n2,n3)

2

>A1.insert(0,"v1","v2","v3")

3

=create(f1,f2)

4

>A3.insert(0,22,A1)

5

=json(A3)

A3中生成如下嵌套的序表:

..

A5中生成如下JSON字符串:

..

格式化一下就看的更清楚,即便内外两层序表中都只有一行数据,都生成了数组:

[{

         "f1": 22,

         "f2": [{

                  "n1": "v1",

                  "n2": "v2",

                  "n3": "v3"

         }]

}]

有时期望这种单行的直接生成如下的对象,而非对象数组,把序表换成记录就可以了(A1A3是序表,A1(1)A3(1)是它们的第一条记录)

{

         "f1": 22,

         "f2": {

                  "n1": "v1",

                  "n2": "v2",

                  "n3": "v3"

         }

}

 


A

1

=create(n1,n2,n3)

2

>A1.insert(0,"v1","v2","v3")

3

=create(f1,f2)

4

>A3.insert(0,22,A1(1))

5

=json(A3(1))