By using db<>fiddle, you agree to license everything you submit by Creative Commons CC0.
WITH
data AS (SELECT CAST('{"f1":["v1","v2"],"f2":"v3"}' AS varchar(max)) AS ResponseJSON),
parser AS
(
SELECT
Level = 1,
OpenClose = 1,
P = p.P,
S = SUBSTRING(d.ResponseJSON, 1, NULLIF(p.P, 0) - 1),
C = SUBSTRING(d.ResponseJSON, NULLIF(p.P, 0), 1),
ResponseJSON = SUBSTRING(d.ResponseJSON, NULLIF(p.P, 0) + 1, 999999)
FROM
data AS d
CROSS APPLY (SELECT PATINDEX('%[[{]%', d.ResponseJSON)) AS p (P)
UNION ALL
SELECT
Level = ISNULL(d.OpenClose - 1, 0) + d.Level + ISNULL(oc.OpenClose, 0),
OpenClose = oc.OpenClose,
P = d.P + ISNULL(p.P, 0),
S = SUBSTRING(d.ResponseJSON, 1, p.P - 1),
C = c.C,
ResponseJSON = SUBSTRING(d.ResponseJSON, p.P + 1, 999999)
FROM
parser AS d
CROSS APPLY (VALUES (NULLIF(PATINDEX('%[[{}:,]%', d.ResponseJSON), 0), NULLIF(PATINDEX('%]%', d.ResponseJSON), 0))) AS p_ (a, b)
CROSS APPLY (VALUES (CASE WHEN p_.a < p_.b OR p_.b IS NULL THEN p_.a ELSE p_.b END)) AS p (P)
CROSS APPLY (SELECT SUBSTRING(d.ResponseJSON, p.P, 1)) AS c (C)
CROSS APPLY (SELECT CASE WHEN c.C IN ('[', '{') THEN 1 WHEN c.C IN (']', '}') THEN 0 END) AS oc (OpenClose)
WHERE 1=1
AND p.P <> 0
)
SELECT
*
FROM
parser
OPTION
Level | OpenClose | P | S | C | ResponseJSON |
---|---|---|---|---|---|
1 | 1 | 1 | { | "f1":["v1","v2"],"f2":"v3"} | |
1 | null | 6 | "f1" | : | ["v1","v2"],"f2":"v3"} |
2 | 1 | 7 | [ | "v1","v2"],"f2":"v3"} | |
2 | null | 12 | "v1" | , | "v2"],"f2":"v3"} |
2 | 0 | 17 | "v2" | ] | ,"f2":"v3"} |
1 | null | 18 | , | "f2":"v3"} | |
1 | null | 23 | "f2" | : | "v3"} |
1 | 0 | 28 | "v3" | } |