JSON函数
JSON函数和操作符
json和jsonb 操作符
下文展示了可以用于两种JSON 数据类型(见JSON 类型)的操作符。
->
右操作数类型 : int
描述
获得 JSON 数组元素(索引从 0 开始,负整数从末尾开始计)
示例
1 palopgsql=# select '[{"a":"foo"},{"b":"bar"},{"c":"baz"}]'::json->2;
2 ?column?
3 -------------
4 {"c":"baz"}
5 (1 row)
6 ```
7
8
9##### `->`
10
11右操作数类型
12: text
13
14## 描述
15
16通过键获得 JSON 对象域
17
18## 示例
19
20``` sql
21 palopgsql=# select '{"a": {"b":"foo"}}'::json->'a';
22 ?column?
23 -------------
24 {"b":"foo"}
25 (1 row)
26 ```
27
28
29
30
31
32##### `->>`
33
34右操作数类型
35: int
36
37## 描述
38
39以text形式获得 JSON 数组元素
40
41## 示例
42
43``` sql
44 palopgsql=# select '[1,2,3]'::json->>2;
45 ?column?
46 ----------
47 3
48 (1 row)
49 ```
50
51##### `->>`
52
53右操作数类型
54: text
55
56## 描述
57
58以text形式获得 JSON 对象域
59
60## 示例
61
62``` sql
63 palopgsql=# select '{"a":1,"b":2}'::json->>'b';
64 ?column?
65 ----------
66 2
67 (1 row)
68 ```
69
70
71##### `#>`
72
73右操作数类型
74: `text[]`
75
76## 描述
77
78获取在指定路径的 JSON 对象
79
80
81## 示例
82
83``` sql
84 palopgsql=# select '{"a": {"b":{"c": "foo"}}}'::json#>'{a,b}';
85 ?column?
86 --------------
87 {"c": "foo"}
88 (1 row)
89 ```
90
91
92##### `#>>`
93
94右操作数类型
95: ` text[]`
96
97## 描述
98
99以text形式获取在指定路径的 JSON 对象
100
101## 示例
102
103``` sql
104 palopgsql=# select '{"a":[1,2,3],"b":[4,5,6]}'::json#>>'{a,2}';
105 ?column?
106 ----------
107 3
108 (1 row)
109 ```
110
111
112**注意**
113
114对`json`和`jsonb`类型,这些操作符都有其并行变体。 域/元素/路径抽取操作符返回与其左手输入(`json`或`jsonb`)相同的类型,不过那些被指定为返回`text`的除外,它们的返回值会被强制 为文本。如果该 JSON输入没有匹配请求的正确结构(例如那样的元素不存在),这些域/元素/路径抽取操作符会返回 NULL 而不是失败。 接受整数 JSON 数组下标的域/元素/路径抽取操作符都支持表示从数组末尾开始的负值下标形式。
115
116
117
118
119
120#### 额外的`jsonb`操作符
121
122标准比较操作符只对`jsonb`有效,而不适合`json`。它们遵循在jsonb 索引中给出的B 树操作规则。
123
124如下文中所示,还存在一些只适合`jsonb`的操作符。这些操作符中的很多可以用`jsonb`操作符类索引。`jsonb`包含和存在语义的完整描述可参见JSONB类型参考手册。
125
126##### `@>`
127
128返回值
129: `boolean`
130
131## 描述
132
133左边的 JSON 值是否在顶层包含右边的 JSON 路径/值项?
134
135## 示例
136
137``` sql
138 palopgsql=# select '{"a":1, "b":2}'::jsonb @> '{"b":2}'::jsonb;
139 ?column?
140 ----------
141 t
142 (1 row)
143 ```
144
145
146##### `<@`
147
148返回值
149: `boolean`
150
151## 描述
152
153左边的 JSON 路径/值项是否被包含在右边的 JSON 值的顶层?
154
155## 示例
156
157``` sql
158 palopgsql=# select '{"b":2}'::jsonb <@ '{"a":1, "b":2}'::jsonb;
159 ?column?
160 ----------
161 t
162 (1 row)
163 ```
164
165
166##### `?`
167
168返回值
169: `boolean`
170
171## 描述
172
173键/元素*字符串*是否存在于 JSON 值的顶层?
174
175## 示例
176
177``` sql
178 palopgsql=# select '{"a":1, "b":2}'::jsonb ? 'b';
179 ?column?
180 ----------
181 t
182 (1 row)
183 ```
184
185
186
187##### `?|`
188
189返回值
190: `boolean`
191
192## 描述
193
194这些数组*字符串*中的任何一个是否做为顶层键存在?
195
196## 示例
197
198``` sql
199 palopgsql=# select '{"a":1, "b":2, "c":3}'::jsonb ?| array['b', 'c'];
200 ?column?
201 ----------
202 t
203 (1 row)
204 ```
205
206
207
208##### `?&`
209
210返回值
211: `boolean`
212
213## 描述
214
215是否所有这些数组*字符串*都作为顶层键存在?
216
217## 示例
218
219``` sql
220 palopgsql=# select '["a", "b"]'::jsonb ?& array['a', 'b'];
221 ?column?
222 ----------
223 t
224 (1 row)
225 ```
226
227
228##### `||`
229
230返回值
231: `jsonb`
232
233## 描述
234
235把两个`jsonb`值串接成一个新的`jsonb`值
236
237## 示例
238
239``` sql
240 palopgsql=# select '["a", "b"]'::jsonb || '["c", "d"]'::jsonb;
241 ?column?
242 ----------------------
243 ["a", "b", "c", "d"]
244 (1 row)
245 ```
246
247
248##### `-`
249
250返回值
251: `text[]`
252
253## 描述
254
255从左操作数删除键/值对或者*string* 元素。键/值对基于它们的键值来匹配。
256
257## 示例
258
259``` sql
260 palopgsql=# select '{"a": "b"}'::jsonb - 'a';
261 ?column?
262 ----------
263 {}
264 (1 row)
265 ```
266
267
268##### `-`
269
270返回值
271: `text[]`
272
273## 描述
274
275从左操作数中删除多个键/值对或者*string*元素。键/值对基于它们的键值来匹配。
276
277## 示例
278
279``` sql
280 palopgsql=# select '{"a": "b", "c": "d"}'::jsonb - '{a,c}'::text[];
281 ?column?
282 ----------
283 {}
284 (1 row)
285 ```
286
287
288##### `-`
289
290返回值
291: `integer`
292
293## 描述
294
295删除具有指定索引(负值表示倒数)的数组元素。如果 顶层容器不是数组则抛出一个错误。
296
297## 示例
298
299``` sql
300 palopgsql=# select '["a", "b"]'::jsonb - 1 ;
301 ?column?
302 ----------
303 ["a"]
304 (1 row)
305
306 ```
307
308##### `#-`
309
310返回值
311: `text[]`
312
313## 描述
314
315删除具有指定路径的域或者元素(对于 JSON 数组,负值 表示倒数)
316
317## 示例
318
319``` sql
320 palopgsql=# select '["a", {"b":1}]'::jsonb #- '{1,b}';
321 ?column?
322 -----------
323 ["a", {}]
324 (1 row)
325 ```
326
327
328**注意**
329
330* `||`操作符将其每一个操作数的顶层的元素串接起来。它不会递归 操作。例如,如果两个操作数都是具有公共域名称的对象,结果中的域值将
331只是来自右手操作数的值。
332
333
334#### JSON 创建函数
335
336
337下文展示了可用于创建`json` 和 `jsonb`值的函数(没有用于 `jsonb`的与`row_to_json`和`array_to_json`等价的函数。不过,`to_jsonb`函数提供了这些函数的很大一部分相同的功能)。
338
339##### `to_json()/to_jsonb()`
340
341## 语法
342
343`to_json(anyelement),to_jsonb(anyelement)`
344
345## 描述
346
347把该值返回为json或者jsonb。数组和组合 会被(递归)转换成数组和对象;对于不是数组和组合的值,如果有 从该类型到json的造型,造型函数将被用来执行该 转换;否则将产生一个标量值。对于任何不是数字、布尔、空值的标 量类型,将使用文本表达,在这种风格下它是一个合法的 json或者jsonb值。
348
349## 示例
350
351``` sql
352 palopgsql=# select to_json('Fred said "Hi."'::text);
353 to_json
354 ---------------------
355 "Fred said \"Hi.\""
356 (1 row)
357 ```
358
359
360##### `array_to_json()`
361
362## 语法
363
364`array_to_json(anyarray [, pretty_bool])`
365
366## 描述
367
368把数组作为一个 JSON 数组返回。一个 PalopgSQL 多维数组会成为一个数组 的 JSON 数组。如果pretty_bool为真,将在 第 1 维度的元素之间增加换行。
369
370## 示例
371
372``` sql
373 palopgsql=# select array_to_json('{{1,5},{99,100}}'::int[]);
374 array_to_json
375 ------------------
376 [[1,5],[99,100]]
377 (1 row)
378 ```
379
380
381
382##### `row_to_json()`
383
384## 语法
385
386`row_to_json(record [, pretty_bool])`
387
388## 描述
389
390把行作为一个 JSON 对象返回。如果pretty_bool为真,将在第1层元素之间增加换行。
391
392## 示例
393
394``` sql
395 palopgsql=# select row_to_json(row(1,'foo'));
396 row_to_json
397 ---------------------
398 {"f1":1,"f2":"foo"}
399 (1 row)
400 ```
401
402
403
404##### `json_build_array()/jsonb_build_array()`
405
406## 语法
407
408`json_build_array(VARIADIC "any"),jsonb_build_array(VARIADIC "any")`
409
410## 描述
411
412从一个可变参数列表构造一个可能包含异质类型的 JSON 数组。
413
414## 示例
415
416``` sql
417 palopgsql=# select json_build_array(1,2,'3',4,5);
418 json_build_array
419 -------------------
420 [1, 2, "3", 4, 5]
421 (1 row)
422 ```
423
424
425##### `json_build_object()/jsonb_build_object()`
426
427## 语法
428
429`json_build_object(VARIADIC "any"),jsonb_build_object(VARIADIC "any")`
430
431## 描述
432
433从一个可变参数列表构造一个 JSON 对象。通过转换,该参数列表由交替 出现的键和值构成。
434
435## 示例
436
437``` sql
438 palopgsql=# select json_build_object('foo',1,'bar',2);
439 json_build_object
440 ------------------------
441 {"foo" : 1, "bar" : 2}
442 (1 row)
443 ```
444
445
446
447##### `json_object()/jsonb_object()`
448
449## 语法
450
451`json_object(text[]),jsonb_object(text[])`
452
453## 描述
454
455从一个文本数组构造一个 JSON 对象。该数组必须可以是具有偶数个成员的 一维数组(成员被当做交替出现的键/值对),或者是一个二维数组(每一个 内部数组刚好有 2 个元素,可以被看做是键/值对)。
456
457## 示例
458
459``` sql
460 palopgsql=# select json_object('{a, 1, b, "def", c, 3.5}');
461 json_object
462 ---------------------------------------
463 {"a" : "1", "b" : "def", "c" : "3.5"}
464 (1 row)
465
466 palopgsql=# select json_object('{{a, 1},{b, "def"},{c, 3.5}}');
467 json_object
468 ---------------------------------------
469 {"a" : "1", "b" : "def", "c" : "3.5"}
470 (1 row)
471 ```
472
473
474##### `json_object()/jsonb_object()`
475
476## 语法
477
478`json_object(keys text[], values text[]),jsonb_object(keys text[], values text[])`
479
480## 描述
481
482json_object的这种形式从两个独立的数组得到键/值对。在其 他方面和一个参数的形式相同。
483
484## 示例
485
486``` sql
487 palopgsql=# select json_object('{a, b}', '{1,2}');
488 json_object
489 ------------------------
490 {"a" : "1", "b" : "2"}
491 (1 row)
492 ```
493
494
495
496**注意**
497
498* `array_to_json`和`row_to_json`与`to_json`具有相同的行为,不过它们提供了更好的打印选项。针对`to_json`所描述的行为同样也适用于由其他 JSON 创建函数转换的每个值。
499
500
501* hstore扩展是一个从`hstore`到`json` 的造型,因此通过 JSON创建函数转换的`hstore`值将被表示为 JSON 对象,而不是原始字符串值。
502
503#### JSON 处理
504
505下文展示了可用来处理`json`和`jsonb`值的函数。
506
507##### `json_array_length()/jsonb_array_length()`
508
509## 语法
510
511`json_array_length(json),jsonb_array_length(jsonb)`
512
513返回值
514: int
515
516## 描述
517
518返回最外层 JSON 数组中的元素数量。
519
520## 示例
521
522``` sql
523 palopgsql=# select json_array_length('[1,2,3,{"f1":1,"f2":[5,6]},4]');
524 json_array_length
525 -------------------
526 5
527 (1 row)
528 ```
529
530##### `json_each()/jsonb_each()`
531
532## 语法
533
534`json_each(json),jsonb_each(jsonb)`
535
536返回值
537: `setof key text, value json`
538
539 `setof key text, value jsonb`
540
541## 描述
542
543扩展最外层的 JSON 对象成为一组键/值对。
544
545## 示例
546
547``` sql
548 palopgsql=# select * from json_each('{"a":"foo", "b":"bar"}');
549 key | value
550 -----+-------
551 a | "foo"
552 b | "bar"
553 (2 rows)
554 ```
555
556
557##### `json_each_text()/jsonb_each_text()`
558
559## 语法
560
561`json_each_text(json),jsonb_each_text(jsonb)`
562
563返回值
564: `setof key text, value text`
565
566## 描述
567
568扩展最外层的 JSON 对象成为一组键/值对。返回值将是text类型。
569
570## 示例
571
572``` sql
573 palopgsql=# select * from json_each_text('{"a":"foo", "b":"bar"}');
574 key | value
575 -----+-------
576 a | foo
577 b | bar
578 (2 rows)
579 ```
580
581
582##### `json_extract_path()/jsonb_extract_path()`
583
584## 语法
585
586`json_extract_path(from_json json, VARIADIC path_elems text[]),jsonb_extract_path(from_json jsonb, VARIADIC path_elems text[])`
587
588返回值
589: json,jsonb
590
591## 描述
592
593返回由path_elems指向的 JSON 值(等效于#>操作符)。
594
595## 示例
596
597``` sql
598 palopgsql=# select json_extract_path('{"f2":{"f3":1},"f4":{"f5":99,"f6":"foo"}}','f4');
599 json_extract_path
600 ----------------------
601 {"f5":99,"f6":"foo"}
602 (1 row)
603 ```
604
605##### `json_extract_path_text()/jsonb_extract_path_text()`
606
607## 语法
608
609`json_extract_path_text(from_json json, VARIADIC path_elems text[]),jsonb_extract_path_text(from_json jsonb, VARIADIC path_elems text[])`
610
611返回值
612: text
613
614## 描述
615
616以text返回由path_elems指向的 JSON 值(等效于#>>操作符)。
617
618## 示例
619
620``` sql
621 palopgsql=# select json_extract_path_text('{"f2":{"f3":1},"f4":{"f5":99,"f6":"foo"}}','f4', 'f6');
622 json_extract_path_text
623 ------------------------
624 foo
625 (1 row)
626 ```
627
628
629##### `json_object_keys()/jsonb_object_keys()`
630
631## 语法
632
633`json_object_keys(json),jsonb_object_keys(jsonb)`
634
635返回值
636: setof text
637
638## 描述
639
640返回最外层 JSON 对象中的键集合。
641
642## 示例
643
644``` sql
645 palopgsql=# select json_object_keys('{"f1":"abc","f2":{"f3":"a", "f4":"b"}}');
646 json_object_keys
647 ------------------
648 f1
649 f2
650 (2 rows)
651 ```
652
653
654
655##### `json_populate_record()/jsonb_populate_record()`
656
657## 语法
658
659`json_populate_record(base anyelement, from_json json),jsonb_populate_record(base anyelement, from_json jsonb)`
660
661返回值
662: anyelement
663
664## 描述
665
666扩展from_json中的对象成一个行,它的列匹配由base定义的记录类型(见下文的注释)。
667
668## 示例
669
670``` sql
671 palopgsql=# CREATE TYPE myrowtype AS (a int, b text);
672 CREATE TYPE
673 palopgsql=# select * from json_populate_record(null::myrowtype, '{"a": 1, "b": ["2", "a b"], "c": {"d": 4, "e": "a b c"}}');
674 a | b
675 ---+--------------
676 1 | ["2", "a b"]
677 (1 row)
678 ```
679
680
681##### `json_populate_recordset()/jsonb_populate_recordset()`
682
683## 语法
684
685`json_populate_recordset(base anyelement, from_json json),jsonb_populate_recordset(base anyelement, from_json jsonb)`
686
687返回值
688: setof anyelement
689
690## 描述
691
692扩展from_json中最外的对象数组为一个集合,该集合的列匹配由base定义的记录类型。
693
694## 示例
695
696``` sql
697 palopgsql=# CREATE TYPE myrowtype AS (a int, b text);
698 CREATE TYPE
699 palopgsql=# select * from json_populate_recordset(null::myrowtype, '[{"a":1,"b":2},{"a":3,"b":4}]');
700 a | b
701 ---+---
702 1 | 2
703 3 | 4
704 (2 rows)
705 ```
706
707
708##### `json_array_elements()`
709
710## 语法
711
712`json_array_elements([json|jsonb])`
713
714返回值
715: setof json,setof jsonb
716
717## 描述
718
719把一个 JSON 数组扩展成一个 JSON 值的集合。
720
721## 示例
722
723``` sql
724 palopgsql=# select * from json_array_elements('[1,true, [2,false]]');
725 value
726 -----------
727 1
728 true
729 [2,false]
730 (3 rows)
731 ```
732
733##### `json_array_elements_text()`
734
735## 语法
736
737`json_array_elements_text([json|jsonb])`
738
739返回值
740: setof text
741
742## 描述
743
744把一个 JSON 数组扩展成一个text值集合。
745
746## 示例
747
748``` sql
749 palopgsql=# select * from json_array_elements_text('["foo", "bar"]');
750 value
751 -------
752 foo
753 bar
754 (2 rows)
755 ```
756
757##### `json_typeof()`
758
759## 语法
760
761`json_typeof([json|jsonb])`
762
763返回值
764: text
765
766## 描述
767
768把最外层的 JSON 值的类型作为一个文本字符串返回。可能的类型是: object、array、string、number、 boolean以及null。
769
770## 示例
771
772``` sql
773 palopgsql=# select json_typeof('-123.4');
774 json_typeof
775 -------------
776 number
777 (1 row)
778 ```
779
780##### `json_to_record()`
781
782## 语法
783
784`json_to_record([json|jsonb])`
785
786
787返回值
788: record
789
790## 描述
791
792从一个 JSON 对象(见下文的注解)构建一个任意的记录。正如所有返回record 的函数一样,调用者必须用一个AS子句显式地定义记录的结构。
793
794## 示例
795
796``` sql
797 CREATE TYPE myrowtype AS (a int, b text);
798 select * from json_to_record('{"a":1,"b":[1,2,3],"c":[1,2,3],"e":"bar","r": {"a": 123, "b": "a b c"}}') as x(a int, b text, c int[], d text, r myrowtype);
799 a | b | c | d | r
800 ---+---------+---------+---+---------------
801 1 | [1,2,3] | {1,2,3} | | (123,"a b c")
802 (1 row)
803 ```
804
805
806##### `json_to_recordset()`
807
808## 语法
809
810`json_to_recordset([json|jsonb])`
811
812返回值
813: setof record
814
815## 描述
816
817从一个 JSON 对象数组(见下文的注解)构建一个任意的记录集合。正如所有返回record 的函数一样,调用者必须用一个AS子句显式地定义记录的结构。
818
819## 示例
820
821``` sql
822 palopgsql=# select * from json_to_recordset('[{"a":1,"b":"foo"},{"a":"2","c":"bar"}]') as x(a int, b text);
823 a | b
824 ---+-----
825 1 | foo
826 2 |
827 (2 rows)
828 ```
829
830
831##### `son_strip_nulls()`
832
833## 语法
834
835`son_strip_nulls(from_json [json|jsonb])`
836
837返回值
838: json,jsonb
839
840## 描述
841
842返回from_json,其中所有具有空值的 对象域都被省略。其他空值不动。
843
844## 示例
845
846``` sql
847 palopgsql=# select json_strip_nulls('[{"f1":1,"f2":null},2,null,3]');
848 json_strip_nulls
849 ---------------------
850 [{"f1":1},2,null,3]
851 (1 row)
852 ```
853
854
855##### `jsonb_set()`
856
857## 语法
858
859`jsonb_set(target jsonb, path text[], new_value jsonb[, create_missing boolean])`
860
861返回值
862: jsonb
863
864## 描述
865
866返回target,其中由 path指定的节用 new_value替换,如果 path指定的项不存在并且 create_missing为真(默认为 true)则加上 new_value。正如面向路径的 操作符一样,出现在path中的 负整数表示从 JSON 数组的末尾开始数。
867
868## 示例
869
870``` sql
871 palopgsql=# select jsonb_set('[{"f1":1,"f2":null},2,null,3]', '{0,f1}','[2,3,4]', false);
872 jsonb_set
873 ---------------------------------------------
874 [{"f1": [2, 3, 4], "f2": null}, 2, null, 3]
875 (1 row)
876
877 palopgsql=# select jsonb_set('[{"f1":1,"f2":null},2]', '{0,f3}','[2,3,4]');
878 jsonb_set
879 ---------------------------------------------
880 [{"f1": 1, "f2": null, "f3": [2, 3, 4]}, 2]
881 (1 row)
882 ```
883
884
885
886##### `jsonb_insert()`
887
888## 语法
889
890`jsonb_insert(target jsonb, path text[], new_value jsonb, [insert_after boolean])`
891
892返回值
893: jsonb
894
895## 描述
896
897返回被插入了new_value的target。如果path指定的target节在一个 JSONB 数组中,new_value将被插入到目标之前(insert_after为false,默认情况)或者之后(insert_after为真)。如果path指定的target节在一个 JSONB 对象内,则只有当target不存在时才插入new_value。对于面向路径的操作符来说,出现在path中的负整数表示从 JSON 数组的末尾开始计数。
898
899## 示例
900
901``` sql
902 spalopgsql=# select jsonb_insert('{"a": [0,1,2]}', '{a, 1}', '"new_value"');
903 jsonb_insert
904 -------------------------------
905 {"a": [0, "new_value", 1, 2]}
906 (1 row)
907 ```
908
909
910##### `jsonb_pretty()`
911
912## 语法
913
914`jsonb_pretty(from_json jsonb)`
915
916返回值
917: text
918
919## 描述
920
921把from_json返回成一段 缩进后的 JSON 文本。
922
923## 示例
924
925``` sql
926 palopgsql=# select jsonb_pretty('[{"f1":1,"f2":null},2,null,3]');
927 jsonb_pretty
928 --------------------
929 [ +
930 { +
931 "f1": 1, +
932 "f2": null+
933 }, +
934 2, +
935 null, +
936 3 +
937 ]
938 (1 row)
939 ```
940
941
942
943**注意**
944
945* 很多这些函数和操作符将把 JSON 字符串中的 Unicode 转义转换成合适的单一字符。如果输入类型是`jsonb`,这就没有问题,因为该转换已经完成了。但是对于`json`输入,这可能会导致抛出一个错误(如JSON 类型所述)。
946
947* 虽然函数`json_populate_record`、`json_populate_recordset`、`json_to_record`以及`json_to_recordset`的例子使用了常量,但常见的用法是引用`FROM`子句中的表并且使用其`json`或`jsonb`列之一作为函数的参数。然后抽取出的键值可以被查询的其他部分引用,例如`WHERE`子句和目标列表。以这种方式抽取多个值的性能比用以键为单位的操作符单个抽取它们的性能更好。
948
949 JSON键被匹配到目标行类型中的相同列名。这些函数的JSON类型强制是一种“尽力而为”的方式并且对于某些类型可能得不到想要的值。不出现在目标行类型中的JSON字段将从输出中忽略,而且不匹配任何JSON字段的目标列将为NULL。
950
951* `jsonb_set`和`jsonb_insert`的`path`参数中除最后一项之外的所有项都必须存在于`target`中。如果`create_missing`为假,`jsonb_set`的`path`参数的所有项都必须存在。如果这些条件不满足,则返回的`target`不会被改变。
952
953* 如果最后的路径项是一个对象键,在它不存在且给定了新值的情况下会创建它。如果最后的路径项是一个数组索引,为正值则表示从左边开始计数,为负值表示从右边开始计数 `-1`表示最右边的元素,以此类推。如果该项超过范围 `-array_length .. array_length -1 `并且`create_missing` 为真,则该项为负时把新值加载数组的开始处,而该项为正时把新值加在数组的末尾处。
954
955
956
957* 不要把`json_typeof`函数的`null`返回值与 SQL 的 NULL 弄混。虽然调用`json_typeof('null'::json)`将会返回`null`,但调用`json_typeof(NULL::json)`将会返回一个 SQL 的 NULL。
958
959
960
961* 如果`json_strip_nulls`的参数在任何对象中包含重复的域名称, 结果在语义上可能有所不同,具体取决于它们发生的顺序。这不是
962`jsonb_strip_nulls`的一个问题,因为`jsonb`值 不能具有重复的对象域名称。
963
964
965* 可聚集函数`json_agg`,它可以把记录值聚集成JSON。还有聚集函数`json_object_agg`,它可以把值对聚集成一个 JSON对象。还有它们的`jsonb`等效体,`jsonb_agg`和`jsonb_object_agg`.
966
967
968### JSON 类型
969
970根据[RFC 7159](https://tools.ietf.org/html/rfc7159) 中的说明,JSON 数据类型是用来存储JSON(JavaScript Object Notation) 数据的。这种数据也可以被存储为`text`,但是 JSON 数据类型的优势在于能强制要求每个被存储的值符合 JSON 规则。也有很多 JSON 相关的函
971数和操作符可以用于存储在这些数据类型中的数据,见JSON 函数和操作符。
972
973有两种 JSON 数据类型:`json` 和 `jsonb`。它们*几乎*接受完全相同的值集合作为输入。主要的实际区别之一是效率。`json`数据类型存储输入文本的精准拷贝,处理函数必须在每 次执行时必须重新解析该数据。而`jsonb`数据被存储在一种分解好的二进制格式中,它在输入时要稍慢一些,因为需要做附加的转换。但是`jsonb`在处理时要快很多,因为不需要解析。`jsonb`也支持索引,这也是一个令人瞩目的优势。
974
975由于`json`类型存储的是输入文本的准确拷贝,其中可能会保留在语法 上不明显的、存在于记号之间的空格,还有 JSON对象内部的键的顺序。还有, 如果一个值中的 JSON对象包含同一个键超过一次,所有的键/值对都会被保留(处理函数会把最后的值当作有效值)。相反,`jsonb`不保留空格、不保留对象键的顺序并且不保留重复的对象键。如果在输入中指定了重复的键,只有最后一个值会被保留。
976
977通常,除非有特别特殊的需要(例如遗留的对象键顺序假设),大多数应用应该 更愿意把 JSON 数据存储为`jsonb`。
978
979PalopgSQL对每个数据库只允许一种 字符集编码。因此 JSON类型不可能严格遵守 JSON 规范,除非数据库编码 是 UTF8。尝试直接包括数据库编码中无法表示的字符将会失败。反过来,能
980在数据库编码中表示但是不在 UTF8 中的字符是被允许的。
981
982RFC 7159 允许 JSON 字符串包含`\uXXXX` 所标记的 Unicode 转义序列。在`json`类型的输入函数中,不管数据库编码如何都允许 Unicode 转义,并且只检查语法正确性(即,跟在`\u`后面的四个十六进制位)。但是,`jsonb`的输入函数更加严格:它不允许非 ASCII 字符的 Unicode 转义(高于`U+007F`的那些),除非数据 库编码是UTF8。`jsonb`类型也拒绝`\u0000`(因为PalopgSQL的`text`类型无法表示 它),并且它坚持使用Unicode 代理对来标记位于 Unicode 基本多语言平面之外 的字符是正确的。合法的 Unicode 转义会被转换成等价的 ASCII或 UTF8 字符进 行存储,这包括把代理对折叠成一个单一字符。
983
984**注意**
985
986很多JSON 函数和操作符章节中描述的 JSON 处理函数将把Unicode 转义转换成常规字符,并且将因此抛出和刚才所描述的同样类型的错误(即使它们的输入是类型`json`而不是`jsonb`)。`json`的输入函数不做这些检查是由来已久的,不过它确实允许将 JSON Unicode 转义简单 的(不经处理)存储在一个非 UTF8 数据库编码中。通常,最好尽可能避免在一个非 UTF8 数据库编码的 JSON中混入 Unicode 转义。
987
988在把文本 JSON 输入转换成`jsonb`时,RFC 7159描述 的基本类型会被有效地映射到原生的
989PalopgSQL类型(如表 JSON 基本类型和相应的PalopgSQL类型中所示)。因此,在合法`jsonb`数据的组成上有一些次要额外约束,它们不适合 `json`类型和抽象意义上的 JSON,这些约束对应于有关哪些东西不能被底层数据类型表示的限制。尤其是,`jsonb`将拒绝位于PalopgSQL `numeric`数据类型范围之外的数字,而`json`则不会。这类实现定义的限制是 RFC 7159所允许的。不过,实际上这类问题更可能发生在其他实 现中,因为把JSON 的`number`基本类型表示为 IEEE 754 双精度浮点 是很常见的(这也是RFC 7159 明确期待和允许的)。当在这类系统间使用 JSON 作为一种交换格式时,应该考虑丢失数字精度的风险。
990
991相反地,如表中所述,有一些 JSON 基本类型输入格式上的次要限制并不适用于相应的PalopgSQL类型。
992
993**表 JSON 基本类型和相应的PalopgSQL类型**
994
995| JSON 基本类型 | PalopgSQL类型 | 注释 |
996| --------- | -------------------- | ------------------------------------------------- |
997| `string` | `text` | 不允许`\u0000`,如果数据库编码不是 UTF8,非 ASCII Unicode 转义也是这样 |
998| `number` | `numeric` | 不允许`NaN` 和 `infinity`值 |
999| `boolean` | `boolean` | 只接受小写`true`和`false`拼写 |
1000| `null` | (无) | SQL `NULL`是一个不同的概念 |
1001
1002
1003
1004#### JSON 输入和输出语法
1005
1006RFC 7159 中定义了 JSON 数据类型的输入/输出语法。
1007
1008下列都是合法的`json`(或者`jsonb`)表达式:
1009
1010``` sql
1011-- 简单标量/基本值
1012-- 基本值可以是数字、带引号的字符串、true、false或者null
1013SELECT '5'::json;
1014
1015-- 有零个或者更多元素的数组(元素不需要为同一类型)
1016SELECT '[1, 2, "foo", null]'::json;
1017
1018-- 包含键值对的对象
1019-- 注意对象键必须总是带引号的字符串
1020SELECT '{"bar": "baz", "balance": 7.77, "active": false}'::json;
1021
1022-- 数组和对象可以被任意嵌套
1023SELECT '{"foo": [true, "bar"], "tags": {"a": 1, "b": null}}'::json;
如前所述,当一个 JSON 值被输入并且接着不做任何附加处理就输出时, json会输出和输入完全相同的文本,而jsonb则不会保留语义上没有意义的细节(例如空格)。例如,注意下面的不同:
1SELECT '{"bar": "baz", "balance": 7.77, "active":false}'::json;
2 json
3-------------------------------------------------
4 {"bar": "baz", "balance": 7.77, "active":false}
5(1 row)
6
7SELECT '{"bar": "baz", "balance": 7.77, "active":false}'::jsonb;
8 jsonb
9--------------------------------------------------
10 {"bar": "baz", "active": false, "balance": 7.77}
11(1 row)
值得一提的一种语义上无意义的细节是,在jsonb中数据会被按照底层 numeric类型的行为来打印。实际上,这意味着用E记号输入的数字被打印出来时就不会有该记号,例如:
1SELECT '{"reading": 1.230e-5}'::json, '{"reading": 1.230e-5}'::jsonb;
2 json | jsonb
3-----------------------+-------------------------
4 {"reading": 1.230e-5} | {"reading": 0.00001230}
5(1 row)
不过,如这个例子所示,jsonb将会保留拖尾的小数点后的零,即便这 对于等值检查等目的来说是语义上无意义的。
有效地设计 JSON 文档
将数据表示为 JSON 比传统关系数据模型要灵活得多,在需求不固定时 这种优势更加令人感兴趣。在同一个应用里非常有可能有两种方法共存并且互补。不过,即便是在要求最大灵活性的应用中,我们还是推荐 JSON文档有固定的结构。该结构通常是非强制的(尽管可能会强制一些业务规则),但是有一个可预测的结构会使书写概括一个表中的“文档”(数据)集合的查询更容易。
当被存储在表中时,JSON 数据也像其他数据类型一样服从相同的并发 控制考虑。尽管存储大型文档是可行的,但是要记住任何更新都在整行上要求一个行级锁。为了在更新事务之间减少锁争夺,可考虑把 JSON 文档限制到一个可管理的尺寸。理想情况下,JSON文档应该每个表示 一个原子数据,业务规则命令不会进一步把它们划分成更小的可独立修 改的数据。
jsonb 包含和存在
测试包含是jsonb的一种重要能力。对 json类型没有平行的功能集。包含测试会测试一个
jsonb文档是否被包含在另一个文档中。除了特别注解 之外,这些例子都会返回真:
1-- 简单的标量/基本值只包含相同的值:
2SELECT '"foo"'::jsonb @> '"foo"'::jsonb;
3
4-- 右边的数字被包含在左边的数组中:
5SELECT '[1, 2, 3]'::jsonb @> '[1, 3]'::jsonb;
6
7-- 数组元素的顺序没有意义,因此这个例子也返回真:
8SELECT '[1, 2, 3]'::jsonb @> '[3, 1]'::jsonb;
9
10-- 重复的数组元素也没有关系:
11SELECT '[1, 2, 3]'::jsonb @> '[1, 2, 2]'::jsonb;
12
13-- 右边具有一个单一键值对的对象被包含在左边的对象中:
14SELECT '{"product": "PalopgSQL", "version": 9.4, "jsonb": true}'::jsonb @> '{"version": 9.4}'::jsonb;
15
16-- 右边的数组不会被认为包含在左边的数组中,
17-- 即使其中嵌入了一个相似的数组:
18SELECT '[1, 2, [1, 3]]'::jsonb @> '[1, 3]'::jsonb; -- 得到假
19
20-- 但是如果同样也有嵌套,包含就成立:
21SELECT '[1, 2, [1, 3]]'::jsonb @> '[[1, 3]]'::jsonb;
22
23-- 类似的,这个例子也不会被认为是包含:
24SELECT '{"foo": {"bar": "baz"}}'::jsonb @> '{"bar": "baz"}'::jsonb; -- 得到假
25
26-- 包含一个顶层键和一个空对象:
27SELECT '{"foo": {"bar": "baz"}}'::jsonb @> '{"foo": {}}'::jsonb;
一般原则是被包含的对象必须在结构和数据内容上匹配包含对象,这种匹配 可以是从包含对象中丢弃了不匹配的数组元素或者对象键值对之后成立。但是记住做包含匹配时数组元素的顺序是没有意义的,并且重复的数组元素实 际也只会考虑一次。
结构必须匹配的一般原则有一种特殊情况,一个数组可以包含一个基本值:
1-- 这个数组包含基本字符串值:
2SELECT '["foo", "bar"]'::jsonb @> '"bar"'::jsonb;
3
4-- 反之不然,下面的例子会报告“不包含”:
5SELECT '"bar"'::jsonb @> '["bar"]'::jsonb; -- 得到假
jsonb还有一个存在操作符,它是包含的一种 变体:它测试一个字符串(以一个text值的形式给出)是否出现在jsonb值顶层的一个对象键或者数组元素中。除非特别注解, 下面这些例子返回真:
1-- 字符串作为一个数组元素存在:
2SELECT '["foo", "bar", "baz"]'::jsonb ? 'bar';
3
4-- 字符串作为一个对象键存在:
5SELECT '{"foo": "bar"}'::jsonb ? 'foo';
6
7-- 不考虑对象值:
8SELECT '{"foo": "bar"}'::jsonb ? 'bar'; -- 得到假
9
10-- 和包含一样,存在必须在顶层匹配:
11SELECT '{"foo": {"bar": "baz"}}'::jsonb ? 'bar'; -- 得到假
12
13-- 如果一个字符串匹配一个基本 JSON 字符串,它就被认为存在:
14SELECT '"foo"'::jsonb ? 'foo';
当涉及很多键或元素时,JSON 对象比数组更适合于做包含或存在测试, 因为它们不像数组,进行搜索时会进行内部优化,并且不需要被线性搜索。
提示
由于 JSON 的包含是嵌套的,因此一个恰当的查询可以跳过对子对象的显式选择。 例如,假设我们在顶层有一个doc列包含着对象,大部分对象包含着tags域,其中有子对象的数组。这个查询会找到其中出现了同时包含"term":"paris"和"term":"food"的子对象
的项,而忽略任何位于tags数组之外的这类键:
1SELECT doc->'site_name' FROM websites
2 WHERE doc @> '{"tags":[{"term":"paris"}, {"term":"food"}]}';
可以用下面的查询完成同样的事情:
1SELECT doc->'site_name' FROM websites
2 WHERE doc->'tags' @> '[{"term":"paris"}, {"term":"food"}]';
但是后一种方法灵活性较差,并且常常也效率更低。
在另一方面,JSON 的存在操作符不是嵌套的:它将只在 JSON 值的顶层 查找指定的键或数组元素。
JSON 函数和操作符中记录了多个包含和存在操作符,以及所有其他 JSON 操作符和函数。
jsonb 索引
GIN 索引可以被用来有效地搜索在大量jsonb文档(数据)中出现 的键或者键值对。提供了两种 GIN“操作符类”,它们在性能和灵活性方面做出了不同的平衡。
jsonb的默认 GIN 操作符类支持使用@>、 ?、?&以及?|操作符的查询(这些操作符实现的详细语义请见表 额外的jsonb操作符)。
使用这种操作符类创建一个索引的例子:
1CREATE INDEX idxgin ON api USING gin (jdoc);
非默认的 GIN 操作符类jsonb_path_ops只支持索引 @>操作符。使用这种操作符类创建一个索引的例子:
1CREATE INDEX idxginp ON api USING gin (jdoc jsonb_path_ops);
考虑这样一个例子:一个表存储了从一个第三方 Web 服务检索到的 JSON 文档,并且有一个模式定义。一个典型的文档:
1{
2 "guid": "9c36adc1-7fb5-4d5b-83b4-90356a46061a",
3 "name": "Angela Barton",
4 "is_active": true,
5 "company": "Magnafone",
6 "address": "178 Howard Place, Gulf, Washington, 702",
7 "registered": "2009-11-07T08:53:22 +08:00",
8 "latitude": 19.793713,
9 "longitude": 86.513373,
10 "tags": [
11 "enim",
12 "aliquip",
13 "qui"
14 ]
15}
我们把这些文档存储在一个名为api的表的名为 jdoc的jsonb列中。如果在这个列上创建一个 GIN索引,下面这样的查询就能利用该索引:
1-- 寻找键 "company" 有值 "Magnafone" 的文档
2SELECT jdoc->'guid', jdoc->'name' FROM api WHERE jdoc @> '{"company": "Magnafone"}';
不过,该索引不能被用于下面这样的查询,因为尽管操作符? 是可索引的,但它不能直接被应用于被索引列jdoc:
1-- 寻找这样的文档:其中的键 "tags" 包含键或数组元素 "qui"
2SELECT jdoc->'guid', jdoc->'name' FROM api WHERE jdoc -> 'tags' ? 'qui';
但是,通过适当地使用表达式索引,上述查询也能使用一个索引。 如果对"tags"键中的特定项的查询很常见,可能值得 定义一个这样的索引:
1CREATE INDEX idxgintags ON api USING gin ((jdoc -> 'tags'));
现在,WHERE 子句 jdoc -> 'tags' ? 'qui' 将被识别为可索引操作符?在索引表达式jdoc ->'tags'上的应用(更多有关表达式索引的信息可见表达式索引)。
另一种查询的方法是利用包含,例如:
1-- 寻找这样的文档:其中键 "tags" 包含数组元素 "qui"
2SELECT jdoc->'guid', jdoc->'name' FROM api WHERE jdoc @> '{"tags": ["qui"]}';
jdoc列上的一个简单 GIN 索引就能支持这个查询。 但是注意这样一个索引将会存储jdoc列中每一个键和值的拷贝,然而前一个例子的表达式索引只存储tags键下找到的数据。虽然简单索引的方法更加灵活(因为它支持有关任意键的查询),定向的表达式索引更小并且搜索速度比简单索引更快。
尽管jsonb_path_ops操作符类只支持用 @>操作符的查询,但它比起默认的操作符类jsonb_ops有更客观的性能优势。一个jsonb_path_ops索引通常也比一个相同数据上的jsonb_ops要小得多,并且搜索的专一性更好,特别是当查询包含频繁出现在该数据中的键时。因此,其上的搜索操作通常比使用默认操作符类的搜索表现更好。
jsonb_ops和jsonb_path_ops GIN 索引之间的技术区别是前者为数据中的每一个键和值创建独立的索引项,而后者值为该数据中的每个值创建索引项。
基本上,每一个jsonb_path_ops索引项是其所对应的值和键的哈希。例如要索引{"foo": {"bar": "baz"}},将创建一个单一的索引项,它把所有三个foo、bar、和baz合并到哈希值中。因此一个查找这个结构的包含查询可能导致极度详细的索引搜索。但是根本没有办法找到foo是否作为 一个键出现。在另一方面,一个jsonb_ops会创建三个索引项分别表示foo、bar和baz。那么要 做同样的包含查询,它将会查找包含所有三个项的行。虽然 GIN索引能够相当 有效地执行这种 AND 搜索,它仍然不如等效的jsonb_path_ops搜索那样详细和快速(特别是如果有大量行包含三个索引项中的任意一个时)。
jsonb_path_ops方法的一个不足是它不会为不包含任何值 的 JSON 结构创建索引项,例如{"a": {}}。如果需要搜索包含这样一种结构的文档,它将要求一次全索引扫描,那就非常慢。 因此jsonb_path_ops不适合经常执行这类搜索的应用。
jsonb也支持btree和hash索引。 这通常值用于检查完整 JSON 文档等值非常重要的场合。jsonb数据的btree顺序很少有人关系,但是为了完整性其顺序是:
1对象 > 数组 > 布尔 > 数字 > 字符串 > 空值
2
3带有 n 对的对象 > 带有 n - 1 对的对象
4
5带有 n 个元素的数组 > 带有 n - 1 个元素的数组
具有相同数量对的对象这样比较:
1key-1, value-1, key-2 ...
注意: 对象键被按照它们的存储顺序进行比较,特别是由于较短的键被存储在 较长的键之前,这可能导致结果不直观,例如:
1{ "aa": 1, "c": 1} > {"b": 1, "d": 1}
相似地,具有相同元素数量的数组按照以下顺序比较:
1element-1, element-2 ...
基本 JSON 值的比较会使用低层PalopgSQL数据类型相同的比较规则进行。字符串的比较会使用默认的数据库排序规则。
转换
有一些附加的扩展可以为不同的过程语言实现jsonb类型的转换。
PL/Perl的扩展被称作jsonb_plperl和jsonb_plperlu。如果使用它们,jsonb值会视情况被映射为Perl的数组、哈希和标量。
PL/Python的扩展被称作jsonb_plpythonu、jsonb_plpython2u和jsonb_plpython3u。如果使用它们,jsonb值会视情况被映射为Python的词典、列表和标量。
对于这种目的,术语“值”包括数组元素,尽管JSON 的术语有时 认为数组元素与对象内的值不同。
评价此篇文章
