我正在尝试编写一个相当复杂的 SQL 查询,生成 JSON 作为结果。一切都工作得很好,除了一些硬编码数组,我需要在层次结构中更深入,我必须使用 UNION ALL
创造。我生成了一个查询,在此处显示了我的问题(不需要数据 - 我在 Azure SQL 数据库中运行此查询):
SELECT
'Hi' AS Greeting,
(
SELECT
CASE WHEN DatePart(second, GetDate()) % 2 = 1 THEN
'qwerty'
ELSE
'asdf'
END AS Stuff
FOR JSON PATH
) AS StuffArray,
(
CASE WHEN DatePart(second, GetDate()) % 2 = 1 THEN
(
SELECT 'qwerty' AS Stuff
FOR JSON PATH
)
ELSE
(
SELECT 'asdf' AS Stuff
FOR JSON PATH
)
END
) AS QuotedStuffArray,
(
CASE WHEN DatePart(second, GetDate()) % 2 = 1 THEN
(
SELECT * FROM
(
SELECT 'qwerty' AS Stuff
UNION ALL
SELECT 'zxcvb' AS Stuff
) AS SubSelect
FOR JSON PATH
)
ELSE
(
SELECT 'asdf' AS Stuff
FOR JSON PATH
)
END
) AS WhyItMatters,
(
SELECT * FROM
(
SELECT 'qwerty' AS Stuff
UNION ALL
SELECT 'zxcvb' AS Stuff
) AS SubSelect
FOR JSON PATH
) AS ButThisIsFine
FOR JSON PATH
这将输出此 JSON:
[
{
"Greeting": "Hi",
"StuffArray": [
{
"Stuff": "qwerty"
}
],
"QuotedStuffArray": "[{\"Stuff\":\"qwerty\"}]",
"WhyItMatters": "[{\"Stuff\":\"qwerty\"},{\"Stuff\":\"zxcvb\"}]",
"ButThisIsFine": [
{
"Stuff": "qwerty"
},
{
"Stuff": "zxcvb"
}
]
}
]
在此查询中,您将在基础对象之外的层次结构中看到四个不同的对象: StuffArray
, QuotedStuffArray
, WhyItMatters
,和ButThisIsFine
。 StuffArray
object 正是我想要的所有对象的样子 - 纯 JSON,没有任何转义。然而,当我开始把我的SELECT
我的 CASE
内的语法声明后,我的结果开始被引用,如QuotedStuffArray
所示目的。所以对于前两个对象来说,这很好。但我有一个问题,有时需要执行条件 UNION
两个硬编码值迫使我将 SELECT
进入CASE
声明如WhyItMatters
所示目的。 ButThisIsFine
对象生成的输出格式就像我想要的 WhyItMatters
要格式化的对象,但它删除了条件 UNION
,我需要。
我怎样才能得到最后这个WhyItMatters
对象生成没有转义引号的纯 JSON,就像 ButThisIsFine
一样对象,同时保持该条件 UNION
声明?
最佳答案
此查询的优化器中发生了一些令人着迷的行为,我不确定这是否是一个错误。以下查询将不会添加转义:
SELECT
'Hi' AS Greeting,
(
CASE WHEN 1 = 1 THEN (
SELECT * FROM (
SELECT 'qwerty' AS [Stuff]
UNION ALL
SELECT 'zxcvb' AS [Stuff]
) _
FOR JSON PATH
) ELSE (
SELECT 'asdf' AS [Stuff]
FOR JSON PATH
)
END
) AS WhyItMatters
FOR JSON PATH
CASE
可以被优化掉,并且它被优化掉,最终结果是很好的嵌套 JSON。但是,如果我们删除优化功能,它就会退化为粘贴转义字符串:
SELECT
'Hi' AS Greeting,
(
CASE WHEN RAND() = 1 THEN (
SELECT * FROM (
SELECT 'qwerty' AS [Stuff]
UNION ALL
SELECT 'zxcvb' AS [Stuff]
) _
FOR JSON PATH
) ELSE (
SELECT 'asdf' AS [Stuff]
FOR JSON PATH
)
END
) AS WhyItMatters
FOR JSON PATH
一个查询会导致处理类型化 JSON,而另一个查询则不会,这似乎不合逻辑,但就是这样。 JSON
不是 T-SQL 中的实际类型(与 XML
不同),因此我们无法进行 CAST
或 CONVERT
>,但是 JSON_QUERY
会做大致相同的事情:
SELECT
'Hi' AS Greeting,
JSON_QUERY(
CASE WHEN RAND() = 1 THEN (
SELECT * FROM (
SELECT 'qwerty' AS [Stuff]
UNION ALL
SELECT 'zxcvb' AS [Stuff]
) _
FOR JSON PATH
) ELSE (
SELECT 'asdf' AS [Stuff]
FOR JSON PATH
)
END
) AS WhyItMatters
FOR JSON PATH
请注意,如果参数已经是 JSON(在常量情况下),这也适用,因此无论如何添加都是安全的。
关于sql-server - 如何防止 FOR JSON PATH 转义查询结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45927168/