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))