JSON值的规范化、合并和自动包装html
当一个字符串被解析并发现是一个有效的JSON文档时,它也会被规范化。这意味着,具备与稍后在文档中找到的键(从左到右)重复的键的成员将被丢弃。JSON_OBJECT()调用生成的对象值只包含第二个key1元素,由于该键名在以前值中出现过,以下所示:mysql
在JSON列中插入值时也会执行规范化,以下所示:算法
这种"最后一次重复的键获胜"的行为是由RFC 7159建议的,而且已由大多数JavaScript解析器实现。(Bug #86866, Bug #26369555)sql
在MySQL 8.0.3以前的版本中,与文档中先前找到的key重复的key成员将被丢弃。如下JSON_OBJECT()调用生成的对象值不包括第二个key1元素,由于该键名在前面出现过:json
在MySQL 8.0.3以前,在向JSON列中插入值时,也会执行"第一个重复键获胜"的规范化。数组
MySQL还会丢弃原始JSON文档中键、值或元素之间的多余空格,并在显示时在每一个逗号(,)或冒号(:)后保留(或在必要时插入)一个空格。这样作是为了提升可读性。并发
产生JSON值的MySQL函数老是返回规范化的值。ide
为了提升查找效率,MySQL还对JSON对象的键进行排序。应该意识到,此排序的结果可能会发生更改,而且不能保证在不一样版本之间保持一致。函数
合并JSON值spa
MySQL8.0.3(及更高版本)支持两种合并算法,由函数JSON_MERGE_PRESERVE()和JSON_MERGE_PATCH()实现。它们在处理重复键的方式上有所不一样:JSON_MERGE_PRESERVE()保留重复键的值,而JSON_MERGE_PATCH()将丢弃除最后一个值以外的全部值。接下来的几段将解释这两个函数如何处理JSON文档的不一样组合(即对象和数组)的合并。
注意
JSON_MERGE_PRESERVE()与早期版本的MySQL(在MySQL 8.0.3中重命名)中的JSON_MERGE()函数相同。在MySQL8.0中,JSON_MERGE()仍然以JSON_MERGE_PRESERVE()别名被支持,但已弃用,并可能在未来的版本中删除。
合并数组。在组合多个数组的上下文中,数组被合并成一个。JSON_MERGE_PRESERVE()经过将后面说起的数组链接到第一个数组的末尾来实现这一点。JSON_MERGE_PATCH()将每一个参数视为一个由单个元素组成的数组(所以其索引为0),而后应用"最后一个重复键获胜"逻辑来仅选择最后一个参数。您能够比较此查询显示的结果:
多个对象合并后生成一个对象。JSON_MERGE_PRESERVE()把数组中具备相同键的对象各惟一值合并;而后将该数组用做结果中该键的值。JSON_MERGE_PATCH()从左到右丢弃找到重复键的值,这样结果只包含该键的最后一个值。如下查询说明了重复键a的结果差别:
在须要数组值的上下文中使用非数组值是会自动包装的:该值由[和]字符包围以将其转换为数组。在下面的语句中,每一个参数都自动包装为一个数组([1],[2])。而后将这些值合并生成一个结果数组;与前两种状况同样,JSON_MERGE_PRESERVE()组合具备相同键的值,而JSON_MERGE_PATCH()将丢弃除最后一个外的全部重复键的值,以下所示:
数组和对象值的合并是经过将对象自动包装为一个数组,并经过合并值来合并数组,或者根据"最后的重复键获胜"原则(分别对应选择的合并函数是JSON_MERGE_PRESERVE()或JSON_MERGE_PATCH())合并数组,如本例所示:
搜索和修改JSON值
JSON路径表达式在JSON文档中选择一个值。
路径表达式指定操做文档位置,对于提取或修改JSON文档内容的函数很是有用。例如,如下查询从JSON文档中提取具备name键的成员的值:
路径语法使用前导的$字符来表示处理中的JSON文档,后面能够跟选择器(可选),这些选择器依次指示文档中更具体的部分:
●一个句点后跟一个键名,用给定的键命名对象中的成员。若是不带引号的键名称在路径表达式中不合法(例如,若是它包含空格),则必须用在双引号包含指定键名称。
● [N]附加到选择数组的路径后,表示在数组中位置N处的值。数组位置是以零开头的整数。若是路径未选择数组值,则路径[0]的计算结果与路径相同:
●[M to N]指定数组值的子集或范围,从位置M处的值开始,到位置N处的值结束。
支持用last做为最右边数组元素的索引的同义词。还支持数组元素的相对寻址。若是path没有选择数组值,path[last]的计算结果与path相同,如本节后面部分所示。
●路径能够包含*或**通配符:
■ .[*]计算JSON对象中全部成员的值。
■ [*]计算JSON数组中全部元素的值。
■ prefix**suffix计算以prefix开头、以suffix结束的全部路径。
● 文档中不存在的路径(计算结果为不存在的数据)计算结果为NULL。
让$引用包含三个元素的JSON数组:
而后:
● $[0]的计算结果为3。
● $[1]的计算结果为{"a": [5, 6], "b": 10}。
● $[2]的计算结果为[99, 100]。
● $[3]的计算结果为NULL(它引用第四个数组元素,它不存在)。
因为$[1]和$[2]的计算结果为非标量值,所以能够用更具体的路径表达式对它们选择嵌套的值。示例:
●$[1].a的计算结果为[5, 6]。
●$[1].a[1]的计算结果为6。
●$[1].b的值为10。
●$[2][0]的计算结果为99。
如前所述,若是未加引号的键名称在路径表达式中不合法,则必须用引号将键引发。让$来引用此值:
两个键都包含空格,必须用引号引用:
●$."a fish"的计算结果是shark。
●$."a bird"的计算结果是sparrow。
使用通配符的路径计算的数组能够包含多个值:
在如下示例中,路径$**.b计算为多个路径($.a.b和$.c.b),并生成匹配路径值的数组:
JSON数组区间。能够使用带有to关键字的区间来指定JSON数组的子集。例如,$[1 to 3]包括数组的第2、第三和第四个元素,以下所示:
语法是 M to N,其中M和N分别是JSON数组中一系列元素的第一个和最后一个索引。N必须大于M;M必须大于或等于0。数组元素以0开头编制索引。
能够在支持通配符的上下文中使用区间。