将没有标头的嵌套 JSON 解析到 SQL 数据库中

问题描述 投票:0回答:1

我有一个没有标头的嵌套 JSON,无法使用 SQL 解析它。我正在尝试将这些数据放入 SQL 表中。这是数据样本

[[123,1123,"94.05",[[11234,31040,"100.00",[[112345,252783,20,"Pass","YES"],[61169237,252785,5,"Pass","YES"],[61169238,252788,5,"Pass","YES"]]]]]]

这是我的询问。我能够解析 JSON 的第一部分,但不能解析嵌套的部分。我如何引用嵌套的 JSON,因为它们没有标头。

SELECT m.[udAuditID]
  ,m.[assessmentID]
  ,m.category_json
  ,s.CatID
  ,s.CategoryID
  ,s.Score
  ,s.SecID
  ,s.SectionID
FROM [dbo].auditfinal m
CROSS APPLY OPENJSON(m.category_json) WITH (
             CatID BIGINT '$[0]',
             CategoryID BIGINT '$[1]',
             Score VARCHAR(max)'$[2]',
             SecID BIGINT '$[0][0]',
             SectionID BIGINT '$[0][1]'
             ) s

正如您在下面的结果中看到的,我能够解析以黄色显示的第一组,但不能超出范围。

在此输入图片描述

感谢您提供的任何帮助或建议!

sql json sql-server azure nested
1个回答
0
投票

如果您的 JSON 包含嵌套块/数组,您可以继续添加更多

APPLY
子查询,直到到达最底部。

如果您的 JSON 模式是静态的,您可能可以构建一个固定的查询,该查询将为您提供所需的一切。沿着这些思路:

-- Your example JSON value
declare @v nvarchar(max) = N'[
    [
        123,
        1123,
        "94.05",
        [
            [
                11234,
                31040,
                "100.00",
                [
                    [ 112345, 252783, 20, "Pass", "YES" ],
                    [ 61169237, 252785, 5, "Pass", "YES" ],
                    [ 61169238, 252788, 5, "Pass", "YES" ]
                ]
            ]
        ]
    ]
]';

select *
from openjson(@v, '$[0]') r
    outer apply (
        select a.[key] as [Key2], a.value as [V2], a.type as [Type2]
        from openjson(r.value, '$[0]') a
        where r.type = 4
    ) l1
    outer apply (
        select b.[key] as [Key3], b.value as [V3], b.type as [Type3]
        from openjson(l1.V2, '$') b
        where l1.Type2 = 4
    ) l2
    outer apply (
        select c.[key] as [Key4], c.value as [V4], c.type as [Type4]
        from openjson(l2.V3, '$') c
        where l2.Type3 = 4
    ) l3;

为了避免

OPENJSON
尝试解析非 JSON 值时出现问题,每个嵌套子查询都有
type = 4
过滤器,因此只会尝试 JSON 对象,而不是标量值。

如果您的 JSON 结构是动态且不可预测的,您将需要某种通用的分层解析器。下面的示例可以作为起点。只是不要指望它会很快。

-- Based on the same variable as above
with cte as (
    select cast(r.[key] as varchar(max)) as [AxisPath], r.value as [Value],
        r.type as [ValueType]
    from openjson(@v, '$') r
    union all
    select c.AxisPath + '.' + cast(d.[key] as varchar(max)), d.value,
        d.type
    from cte c
        cross apply openjson(c.Value, '$') d
    where c.ValueType = 4 -- JSON objects only
)
select *
from cte c
-- Should be no JSON left unparsed in the end
where c.ValueType != 4
order by c.AxisPath;
© www.soinside.com 2019 - 2024. All rights reserved.