Page tree
Skip to end of metadata
Go to start of metadata


1. 内容概述



UnwindJson 是一种表值类型的函数,可分析 JSON 文本,并以行和列的形式返回 JSON 输入的对象和属性。

换句话说,UnwindJson 对 JSON 文档提供行集视图,可以指定行集中的列以及用于填充列的 JSON 属性路径,它返回一个虚拟表。

我们可以像使用其他真实表一样在SQL语句的 from 子句以及表连接函数 Cross Apply 和 Outer Apply中使用它们。

2. 基本语法




UnwindJson ( jsonExpression [ , jsonPath ] )  [ <with-clause> ]
<with_clause> ::+ WITH ( { colName type [ column_path ] [ AS JSON ] } [,....n]


其中,jsonExpression 为必须项,jsonPath 和 with 语句为可选项。

注意

在使用表值函数时,必须为返回的虚拟表起一个别名,否则SQL语句将被视为无效。

如:select * from UnwindJson(jsonExpression,jsonpath) tmp with (...)

其中 tmp 就是 unwindJson 返回表的别名。后续使用该表时,引用 tmp 即可。


如果不使用 with 子句,UnwindJson 默认返回三列,列名分别为“Key”、“Value” 和“Type”。

比如:

select * from UnwindJson('{"Name":"David","Age":35}') tmp

结果表是:

Key

Value

Type

NameDavid8
Age356


对返回结果表的说明:

列索引

列名

数据类型

描述

0KeystringJSON 属性名
1ValueobjectJSON 属性值
2Typeinteger

此列返回数据类型值。具体请见下表。


3. UnwindJson 返回的数据类型值



数据类型

返回值

None0
Object1
Array2
Constructor3
Property4
Comment5
Integer6
Float7
String8
Boolean9
Null10
Undefined11
Date12
Raw13
Bytes14
Guid15
Uri16
TimeSpan17


接下来为您介绍 UnwindJon 函数中各个参数的含义和具体用法。

4. JsonExpression 参数



JsonExpression 是字符串类型的函数参数,表示 JSON 内容。您可以发送带有任何表达式的值,包括引用列的表达式。

JSON 内容可以是单个JSON 对象或 JSON 数组。

UnwindJson 循环访问 JsonExpression 中的数组元素或对象的属性,并为每个元素或属性返回一行。

JsonExpression 示例:

UnwindJson('{"Name":"David"}')
UnwindJson('[1,2,3]')
UnwindJson('[{"Name":"David"},{"Name":"Sherlock"}]')
UnwindJson(Table1.JsonColumn)
UnwindJson(@commandParameter)

注意

如果jsonExpression为null或无效的JSON结构,则UnwindJson会引发异常。

5. JsonPath 参数



JsonPath 是在 jsonExpression 中引用对象或数组时可选的 JSON 路径表达式。 UnwindJson 会定位到指定位置处的 JSON 文本,并且仅分析引用的片段。 

规则说明:

Jsonpath说明
$根对象/元素
*通配符,指所有对象/元素。
. or [ ]子级对象成员
..递归下降
?( )应用过滤器(脚本)表达式。
@当前的对象/元素
[ , ]

XPath中的Union运算符导致节点集的组合。JSONPath允许将备用名称或数组索引作为一组。

[ ]

下标运算符。在Javascript和JSON中,它是本机数组运算符。

[ start : end : step ]从ES4借鉴的数组切片运算符。


示例:

Jsonpath示例结果说明
$.store.book[*].author商店中所有书籍的作者
$..author所有作者
$.store.*商店里所有的东西,包括一些书和一辆红色的自行车。
$.store..price商店中所有商品的价格。
$..book[2]第三本书
$..book[-1:]最后一本书。
$..book[0,1]
$..book[:2]
前两本书
$..book[?(@.isbn)]过滤所有具有isbn编号的书
$..book[?(@.price<10)]筛选所有价格低于10的书籍
$..*XML文档中的所有元素。JSON结构的所有成员。


严格模式:

如果您在JsonPath的内容之前添加严格的字符串  ,则表明JSON解析器将应用严格模式。

这意味着,如果解析器找不到JsonPath指定的对象,则它将报告错误,而不在严格模式的情况下返回DBNull。

默认不采用严格模式。

以下表达式包含严格模式下的错误:

UnwindJson('{}', 'strict $.Name')
UnwindJson('[1,2]', 'strict $[8]')


即使在严格模式下,也允许选择具有空值的空数组或对象:

UnwindJson('{"Name":null}', 'strict $.Name')
UnwindJson('{"Array":[]}', 'strict $.Array')
UnwindJson('{"Array":[]}', 'strict $.Array[*]')

注意

  • JsonPath参数只能是常量/参数表达式,这意味着它不能引用表的列。以下表达式有效:
UnwindJson('{}', '$')
UnwindJson('{}', @commandParameter)
UnwindJson('{}', '$.'+@commandParameter)
UnwindJson('{}', '$'+'.'+'sth')
  • 如果JsonPath为null或空字符串,则UnwindJson返回的表中没有行。

  • 按照惯例,当Json属性中包含特殊字符  ,。[]()'-@ $ :?* 时,应避免使用  [‘propertyName‘] 格式引用。

UnwindJson('{"FirstName.LastName":"David.Ma"}', '$.[''FirstName.LastName'']')

由于上述JsonPath是按原义格式发送的,因此您可以看到JsonPath中的单引号被手动转义为双引号。如果JsonPath是来自命令参数的,则无需进行任何处理。

6. with 子句



With 子句用于指示 UnwindJson 如何解析JSON内容并填充列数据。

一个with 子句中包含几个(至少一个)列定义,每个都有一个列名,一个数据类型和一个可选的JsonPath描述符。

如下示例中定义了三个列。

WITH (
    UserName  varchar  '$.Name' ,
    Age       integer           ,
    Location  varchar   AS JSON
)

列定义中的数据类型

有效的数据类型包括:Integer, Single, Double, Decimal, Boolean, DateTime, Varchar

列定义中的JsonPath

上例中的UserName 通过解析具有给定路径'$ .Name'的JSON内容,以获得标量值。

列的数据类型被指定为'varchar',这意味着已解析的JSON 内容将转换为字符串。

  • 如果'$ .Name'指向JSON属性,则UserName列的值是该属性的单个值。 
    它可以是整数,布尔值或其他形式,但最终它将被转换为字符串类型,因为指定了'varchar'数据类型。
  • 如果'$ .Name'指向JSON数组,则该值为null。
  • 如果“ $ .Name”指向嵌套的JSON对象,则该值为null。
  • 如果'$ .Name'指向空,则该值为null。 

列定义中的JsonPath也可以使用严格模式。如果将路径更改为“ strict $ .Name”,则会出现错误,提示未选择任何元素。

也可以省略列定义中的 JsonPath,如此的话,列名将作为路径。通过解析带有隐式路径的JSON内容(在此示例中为'$ .Age'),定义Age以获取标量值。

列定义中的AS JSON

上例中的 Location 使用了AS JSON 。

它实际使用了隐式路径“ $ .Location”解析JSON内容,并获取解析的JSON 内容全文。

AS JSON  表示,将已解析的JSON全文都设置为列值。

由于AS JSON始终返回字符串,因此需要显式数据类型 'varchar'。否则将报告错误。

注意

  • AS JSON周围没有单引号。
  • 使用AS JSON选项,该列必须将数据类型定义为“ varchar”

7. 示例讲解


UnwindJson(jsonExpression)

如果jsonExpression是JSON对象,则UnwindJson函数将列出所有属性及其值。

如果jsonExpression是JSON数组,它将列出所有数组元素的值。

示例1. 以下SQL扩展了JSON对象的所有属性:

select * from UnwindJson('{"Name":"David","Age":35}') tmp

结果表是:

Key

Value

Type

NameDavid8
Age356

对返回结果表的说明:

列索引

列名

数据类型

描述

0KeystringJSON 属性名
1ValueobjectJSON 属性值
2Typeinteger

此列返回数据类型值,详见 UnwindJson 返回的数据类型值



示例2. 以下SQL 扩展了JSON对象的数组元素:

select * from UnwindJson('[1,3,"hi"]') tmp

结果表是:

Key

Value

Type

016
126
2hi8


对返回结果表的说明:

列索引

列名

数据类型

描述

0Keystring数组元素索引的字符串格式
1Valueobject数组元素的值
2Typeinteger

此列返回数据类型值,详见 UnwindJson 返回的数据类型值


示例3. 以下SQL列出了复杂的属性:

select * from UnwindJson('{"Name":"David","Tags":["GCEF","DEV"]}') tmp

结果表是:

Key

Value

Type

NameDavid8
Tags["GCEF","DEV"]2

注意

  • JSON对象或数组作为Value将被转换为全文。
  • 强烈建议您将“Value”列转换为期望的数据类型,因为其原始类型是“Object”。
select CSTR(Value) as StringValue from UnwindJson('[1,3,"hi"]') tmp

UnwindJson ( jsonExpression, jsonPath)

在 UnwindJson中添加 jsonPath 后,函数将给定JSONPath的jsonExpression进行解析。

结果表的架构为:

列索引

列名

数据类型

说明

0Keystring

解析的JSON内容中索引的字符串格式

1Valueobject解析的Json内容
2Typeinteger

此列返回数据类型值,详见 UnwindJson 返回的数据类型值


示例1. 

select * from UnwindJson('{"String":"David"}', '$.String') tmp

结果表:

Key

Value

Type

0David8

示例2. 

select * from UnwindJson('{"Name":"David","Tags":[{"Group":[1,2]},{"Group":[3]}]}', '$.Tags[*]') tmp

结果表:

Key

Value

Type

0{"Group":[1,2]}1
1{"Group":[3]}1

示例3. 

select * from UnwindJson('{"Name":"David","Tags":[{"Group":[1,2]},{"Group":[3]}]}', '$.Tags[*].Groups[*]') tmp

结果表:

Key

Value

Type

016
126
236

示例4. 

select * from UnwindJson('[{"Data1":[1]},{"Data2":[2]}]', '$[*].*') tmp

结果表:

Key

Value

Type

016
126

UnwindJson ( jsonExpression ) with ( ... )

UnwindJson 函数将按照 with 子句中各列指定的路径提取jsonExpression。

返回表的架构与with子句中定义的完全匹配。

如果jsonExpression是JSON对象,将返回零或一个数据行。

如果jsonExpression是JSON数组,则将返回计数等于数组元素计数的行。

请注意,jsonExpression可能是一个JSON数组,在这种情况下,列定义上的路径基于临时JSON根(实际上是JSON数组的元素)工作。


示例1.

select * from UnwindJson('{"Name":"David","Age":35}') tmp with (
    UserName varchar '$.Name',
    Age  integer
)

结果表:

UserName

Age

David35


示例2:

select * from UnwindJson('[{"Name":"Thomas"},{"Name":"David"}]') tmp with (
    UserName varchar '$.Name'
)


结果表:

UserName

Thomas
David


示例3:

select * from UnwindJson('[{"Name":"Thomas","Tags":[101,102]},{"Name":"David",Tags:[101]}]') tmp with (
    Name varchar ,
    Tags varchar AS JSON
)


结果表:

Name

Tags

Name

Tags

Thomas[101,102]
David[101]


示例4:

select * from UnwindJson('[{"Name":"Thomas","Location":{"City":"XA"}},{"Name":"David","Location":null}]') tmp with (
    Name varchar ,
    City varchar '$.Location.City'
)


结果表:

Name

City

ThomasXA
Davidnull

注意

每个列都可以定义自己的严格模式。

UnwindJson ( jsonExpression, jsonPath ) with ( ... )

UnwindJson函数的这个用法是前一个用法的增强版。

不同的是,在每个列的JsonPath工作之前,使用整个JsonPath提前解析 jsonExpression。

在实际应用场景中,它非常适用 于jsonExpression 是单个JSON对象的场景。

示例:

select * from UnwindJson('{"Company":{"Name":"GrapeCity","Departments":[{"Id":1,"Name":"DD1"},{"Id":2,"Name":"DD2"}]}}', '$.Company.Departments[*]') tmp with (
    Id integer,
    DepartmentName varchar '$.Name'
)

结果表:

Id

DepartmentName

1DD1
2DD2





  • No labels