如何计算 JSON 中所有值的路径
How to work out the path for all values in a JSON
我有一个 JSON 列,其中包含大约 300k 的属性,我想尝试以这样一种方式导出它,以便我可以获得 属性 的完整路径和值.
请注意,我的 JSON 没有数组 - 它基本上是用于 Web 应用程序翻译的 JSON。
使用以下内容提供一个简单示例 JSON 我想返回以下内容:
JSON:
{"Name":"Jeff", "Address": {"Street": "123 Harrow Street", "City": "Dublin"}}
预期输出:
|----------------|-------------------|
| path | value |
|----------------|-------------------|
| Name | Jeff |
| Address.Street | 123 Harrow Street |
| Address.City | Dublin |
|----------------|-------------------|
或者如果使用 $.
更容易,因为我希望能够轻松更新每个 属性 的值 - 使用 JSON_MODIFY
.
我试过使用 OPENJSON 但那只出现在 return 3 个字段键、值和类型中,但至少这里的键不会超过值的字段级别,所以我得到:
查询:
DECLARE @json_doc nvarchar(4000) = '{"Name":"Jeff", "Address": {"Street": "123 Harrow Street", "City": "Dublin"}}';
SELECT [key], [value]
FROM OPENJSON(@json_doc);
GO
输出:
|---------|---------------------------------------------------|
| key | value |
|---------|---------------------------------------------------|
| Name | Jeff |
| Address | {"Street": "123 Harrow Street", "City": "Dublin"} |
|---------|---------------------------------------------------|
有没有办法让 OPENJSON 查询完全递归?或者还有其他方法吗?我试过谷歌搜索,但它似乎不是一个常见的请求?
递归 CTE 是一种选择。您需要在查询的递归成员中使用 ISJSON()
作为终止条件:
DECLARE @json_doc nvarchar(4000) = '{"Name":"Jeff", "Address": {"Street": "123 Harrow Street", "City": "Dublin"}}';
;WITH rCTE AS (
SELECT
CONVERT(nvarchar(max), N'$') COLLATE DATABASE_DEFAULT AS [path],
CONVERT(nvarchar(max), JSON_QUERY(@json_doc, '$')) COLLATE DATABASE_DEFAULT AS [value]
UNION ALL
SELECT
CONVERT(nvarchar(max), CONCAT(r.path, CONCAT(N'.', c.[key]))) COLLATE DATABASE_DEFAULT ,
CONVERT(nvarchar(max), c.[value]) COLLATE DATABASE_DEFAULT
FROM rCTE r
CROSS APPLY OPENJSON(r.[value]) c
WHERE ISJSON(r.[value]) = 1
)
SELECT *
FROM rCTE
WHERE ISJSON([value]) = 0
结果:
path value
----------------------------------
$.Name Jeff
$.Address.Street 123 Harrow Street
$.Address.City Dublin
我有一个 JSON 列,其中包含大约 300k 的属性,我想尝试以这样一种方式导出它,以便我可以获得 属性 的完整路径和值. 请注意,我的 JSON 没有数组 - 它基本上是用于 Web 应用程序翻译的 JSON。
使用以下内容提供一个简单示例 JSON 我想返回以下内容:
JSON:
{"Name":"Jeff", "Address": {"Street": "123 Harrow Street", "City": "Dublin"}}
预期输出:
|----------------|-------------------|
| path | value |
|----------------|-------------------|
| Name | Jeff |
| Address.Street | 123 Harrow Street |
| Address.City | Dublin |
|----------------|-------------------|
或者如果使用 $.
更容易,因为我希望能够轻松更新每个 属性 的值 - 使用 JSON_MODIFY
.
我试过使用 OPENJSON 但那只出现在 return 3 个字段键、值和类型中,但至少这里的键不会超过值的字段级别,所以我得到: 查询:
DECLARE @json_doc nvarchar(4000) = '{"Name":"Jeff", "Address": {"Street": "123 Harrow Street", "City": "Dublin"}}';
SELECT [key], [value]
FROM OPENJSON(@json_doc);
GO
输出:
|---------|---------------------------------------------------|
| key | value |
|---------|---------------------------------------------------|
| Name | Jeff |
| Address | {"Street": "123 Harrow Street", "City": "Dublin"} |
|---------|---------------------------------------------------|
有没有办法让 OPENJSON 查询完全递归?或者还有其他方法吗?我试过谷歌搜索,但它似乎不是一个常见的请求?
递归 CTE 是一种选择。您需要在查询的递归成员中使用 ISJSON()
作为终止条件:
DECLARE @json_doc nvarchar(4000) = '{"Name":"Jeff", "Address": {"Street": "123 Harrow Street", "City": "Dublin"}}';
;WITH rCTE AS (
SELECT
CONVERT(nvarchar(max), N'$') COLLATE DATABASE_DEFAULT AS [path],
CONVERT(nvarchar(max), JSON_QUERY(@json_doc, '$')) COLLATE DATABASE_DEFAULT AS [value]
UNION ALL
SELECT
CONVERT(nvarchar(max), CONCAT(r.path, CONCAT(N'.', c.[key]))) COLLATE DATABASE_DEFAULT ,
CONVERT(nvarchar(max), c.[value]) COLLATE DATABASE_DEFAULT
FROM rCTE r
CROSS APPLY OPENJSON(r.[value]) c
WHERE ISJSON(r.[value]) = 1
)
SELECT *
FROM rCTE
WHERE ISJSON([value]) = 0
结果:
path value
----------------------------------
$.Name Jeff
$.Address.Street 123 Harrow Street
$.Address.City Dublin