动态 JSON 使用 T-SQL 解析
Dynamic JSON Parsing using T-SQL
我有一个高度非结构化的 JSON 字符串,作为调用 REST 的响应 API:
{
"info": "Test Json Structure",
"Owner": "Self-Owned",
"managedObjects": [{
"Name": "Device1",
"Class": "A"
}, {
"Name": "Device2",
"Class_145": "Ax01",
"Class_11": "B",
"Type_125478": {
"Model": "1",
"Manufacturer": "External"
},
"Type_SD": {
"Model": "00",
"Manufacturer": "Internal"
}
}, {
"Name": "Device3",
"Class_x": "Cx11",
"Class_T": "C8Y",
"Type": {
"Model": "1x",
"Manufacturer": "Internal"
}
}
]
}
如何使用 T-SQL 动态解析此对象,以便所有子元素代表 table 的列?更重要的是,如何处理 Type
、Type_125478
、Type_SD
对象,实际上它们具有相同的结构(Model, Manufacturer
),但有些名称不同。还要记住,设备可能会发送一个新的标识符 (Type_XYZ
),它以前不存在,但幸运的是具有相同的结构 (Model, Manufacturer
)。
您可以使用类似这样的方法将 整批 分解为表格结构并继续执行此操作(需要 SQL-Server 版本 v2016+):
DECLARE @YourJSON NVARCHAR(MAX)=
N'{
"info": "Test Json Structure",
"Owner": "Self-Owned",
"managedObjects": [{
"Name": "Device1",
"Class": "A"
}, {
"Name": "Device2",
"Class_145": "Ax01",
"Class_11": "B",
"Type_125478": {
"Model": "1",
"Manufacturer": "External"
},
"Type_SD": {
"Model": "00",
"Manufacturer": "Internal"
}
}, {
"Name": "Device3",
"Class_x": "Cx11",
"Class_T": "C8Y",
"Type": {
"Model": "1x",
"Manufacturer": "Internal"
}
}
]
}';
--查询
SELECT A.info
,A.[Owner]
,C.[key] AS TagName
,CASE WHEN D.Model IS NULL THEN C.[value] END AS TagValue
,D.Model
,D.Manufacturer
FROM OPENJSON(@YourJSON)
WITH(info NVARCHAR(MAX)
,[Owner] NVARCHAR(MAX)
,managedObjects NVARCHAR(MAX) AS JSON) A
OUTER APPLY OPENJSON(A.managedObjects) B
OUTER APPLY OPENJSON(B.[value]) C
OUTER APPLY OPENJSON(CASE WHEN ISJSON(C.[value])=1 THEN C.[value] END)
WITH (Model NVARCHAR(MAX)
,Manufacturer NVARCHAR(MAX))D;
--结果
+---------------------+------------+-------------+----------+-------+--------------+
| info | Owner | TagName | TagValue | Model | Manufacturer |
+---------------------+------------+-------------+----------+-------+--------------+
| Test Json Structure | Self-Owned | Name | Device1 | | |
+---------------------+------------+-------------+----------+-------+--------------+
| Test Json Structure | Self-Owned | Class | A | | |
+---------------------+------------+-------------+----------+-------+--------------+
| Test Json Structure | Self-Owned | Name | Device2 | | |
+---------------------+------------+-------------+----------+-------+--------------+
| Test Json Structure | Self-Owned | Class_145 | Ax01 | | |
+---------------------+------------+-------------+----------+-------+--------------+
| Test Json Structure | Self-Owned | Class_11 | B | | |
+---------------------+------------+-------------+----------+-------+--------------+
| Test Json Structure | Self-Owned | Type_125478 | | 1 | External |
+---------------------+------------+-------------+----------+-------+--------------+
| Test Json Structure | Self-Owned | Type_SD | | 00 | Internal |
+---------------------+------------+-------------+----------+-------+--------------+
| Test Json Structure | Self-Owned | Name | Device3 | | |
+---------------------+------------+-------------+----------+-------+--------------+
| Test Json Structure | Self-Owned | Class_x | Cx11 | | |
+---------------------+------------+-------------+----------+-------+--------------+
| Test Json Structure | Self-Owned | Class_T | C8Y | | |
+---------------------+------------+-------------+----------+-------+--------------+
| Test Json Structure | Self-Owned | Type | | 1x | Internal |
+---------------------+------------+-------------+----------+-------+--------------+
提示:您可以将 B.[key]
作为对象标识符添加到结果中。
简而言之
- 我们用第一个
OPENJSON
进入你的JSON。 WITH
子句允许将 JSON-props 作为列进行寻址。我们 return managedObejcts
作为 JSON 他们自己。
- 我们再使用一个
OPENJSON
来深入研究托管对象。
- 这将 return 一个对象数组。我们可以将
value
传递给另一个 OPENJSON
.
- 每当
value
可以单独解释为 JSON 时,我们再使用一个 OPENJSON
,这次再次使用 WITH
子句来获得内部道具作为列。
您可以将此结果插入 table(声明的、临时的、物理的...)并继续此 easy-to-read 集。
我有一个高度非结构化的 JSON 字符串,作为调用 REST 的响应 API:
{
"info": "Test Json Structure",
"Owner": "Self-Owned",
"managedObjects": [{
"Name": "Device1",
"Class": "A"
}, {
"Name": "Device2",
"Class_145": "Ax01",
"Class_11": "B",
"Type_125478": {
"Model": "1",
"Manufacturer": "External"
},
"Type_SD": {
"Model": "00",
"Manufacturer": "Internal"
}
}, {
"Name": "Device3",
"Class_x": "Cx11",
"Class_T": "C8Y",
"Type": {
"Model": "1x",
"Manufacturer": "Internal"
}
}
]
}
如何使用 T-SQL 动态解析此对象,以便所有子元素代表 table 的列?更重要的是,如何处理 Type
、Type_125478
、Type_SD
对象,实际上它们具有相同的结构(Model, Manufacturer
),但有些名称不同。还要记住,设备可能会发送一个新的标识符 (Type_XYZ
),它以前不存在,但幸运的是具有相同的结构 (Model, Manufacturer
)。
您可以使用类似这样的方法将 整批 分解为表格结构并继续执行此操作(需要 SQL-Server 版本 v2016+):
DECLARE @YourJSON NVARCHAR(MAX)=
N'{
"info": "Test Json Structure",
"Owner": "Self-Owned",
"managedObjects": [{
"Name": "Device1",
"Class": "A"
}, {
"Name": "Device2",
"Class_145": "Ax01",
"Class_11": "B",
"Type_125478": {
"Model": "1",
"Manufacturer": "External"
},
"Type_SD": {
"Model": "00",
"Manufacturer": "Internal"
}
}, {
"Name": "Device3",
"Class_x": "Cx11",
"Class_T": "C8Y",
"Type": {
"Model": "1x",
"Manufacturer": "Internal"
}
}
]
}';
--查询
SELECT A.info
,A.[Owner]
,C.[key] AS TagName
,CASE WHEN D.Model IS NULL THEN C.[value] END AS TagValue
,D.Model
,D.Manufacturer
FROM OPENJSON(@YourJSON)
WITH(info NVARCHAR(MAX)
,[Owner] NVARCHAR(MAX)
,managedObjects NVARCHAR(MAX) AS JSON) A
OUTER APPLY OPENJSON(A.managedObjects) B
OUTER APPLY OPENJSON(B.[value]) C
OUTER APPLY OPENJSON(CASE WHEN ISJSON(C.[value])=1 THEN C.[value] END)
WITH (Model NVARCHAR(MAX)
,Manufacturer NVARCHAR(MAX))D;
--结果
+---------------------+------------+-------------+----------+-------+--------------+
| info | Owner | TagName | TagValue | Model | Manufacturer |
+---------------------+------------+-------------+----------+-------+--------------+
| Test Json Structure | Self-Owned | Name | Device1 | | |
+---------------------+------------+-------------+----------+-------+--------------+
| Test Json Structure | Self-Owned | Class | A | | |
+---------------------+------------+-------------+----------+-------+--------------+
| Test Json Structure | Self-Owned | Name | Device2 | | |
+---------------------+------------+-------------+----------+-------+--------------+
| Test Json Structure | Self-Owned | Class_145 | Ax01 | | |
+---------------------+------------+-------------+----------+-------+--------------+
| Test Json Structure | Self-Owned | Class_11 | B | | |
+---------------------+------------+-------------+----------+-------+--------------+
| Test Json Structure | Self-Owned | Type_125478 | | 1 | External |
+---------------------+------------+-------------+----------+-------+--------------+
| Test Json Structure | Self-Owned | Type_SD | | 00 | Internal |
+---------------------+------------+-------------+----------+-------+--------------+
| Test Json Structure | Self-Owned | Name | Device3 | | |
+---------------------+------------+-------------+----------+-------+--------------+
| Test Json Structure | Self-Owned | Class_x | Cx11 | | |
+---------------------+------------+-------------+----------+-------+--------------+
| Test Json Structure | Self-Owned | Class_T | C8Y | | |
+---------------------+------------+-------------+----------+-------+--------------+
| Test Json Structure | Self-Owned | Type | | 1x | Internal |
+---------------------+------------+-------------+----------+-------+--------------+
提示:您可以将 B.[key]
作为对象标识符添加到结果中。
简而言之
- 我们用第一个
OPENJSON
进入你的JSON。WITH
子句允许将 JSON-props 作为列进行寻址。我们 returnmanagedObejcts
作为 JSON 他们自己。 - 我们再使用一个
OPENJSON
来深入研究托管对象。 - 这将 return 一个对象数组。我们可以将
value
传递给另一个OPENJSON
. - 每当
value
可以单独解释为 JSON 时,我们再使用一个OPENJSON
,这次再次使用WITH
子句来获得内部道具作为列。
您可以将此结果插入 table(声明的、临时的、物理的...)并继续此 easy-to-read 集。