SQL 服务器 JSON 路径动态列名称
SQL Server For JSON Path dynamic column name
我们正在探索 JSON feature in SQL Sever
,对于其中一个场景,我们想提出一个 SQL 可以 return 一个 JSON 如下
[
{
"field": {
"uuid": "uuid-field-1"
},
"value": {
"uuid": "uuid-value" //value is an object
}
},
{
"field": {
"uuid": "uuid-field-2"
},
"value": "1". //value is simple integer
}
... more rows
]
value
字段可以是简单的 integer/string 或嵌套对象。
我们可以想出一个 table 如下所示:
field.uuid | value.uuid | value|
------------|---------- | -----|
uuid-field-1| value-uuid | null |
uuid-field-2| null | 1 |
... more rows
但是一旦我们申请 for json path
,它就失败了
Property 'value' cannot be generated in JSON output due to a conflict with another column name or alias. Use different names and aliases for each column in SELECT list.
是否有可能以某种方式生成它?该值将在 value.uuid
或 value
中,而不是两者?
注意: 如果我们可以将每一行转换为单独的 JSON 并将它们全部添加到一个数组中,我们愿意接受这种可能性。
这个错误的原因是(如documentation中提到的)... FOR JSON PATH 子句使用列别名或列名来确定JSON 输出中的键名。如果别名包含点,则 PATH 选项会创建嵌套对象 。在您的情况下 value.uuid
和 value
都生成一个名称为 value
.
的密钥
我可以推荐一种方法(可能不是最好的方法),它使用 JSON_MODIFY()
从一个空的 JSON 数组生成预期的 JSON:
Table:
CREATE TABLE Data (
[field.uuid] varchar(100),
[value.uuid] varchar(100),
[value] int
)
INSERT INTO Data
([field.uuid], [value.uuid], [value])
VALUES
('uuid-field-1', 'value-uuid', NULL),
('uuid-field-2', NULL, 1),
('uuid-field-3', NULL, 3),
('uuid-field-4', NULL, 4)
声明:
DECLARE @json nvarchar(max) = N'[]'
SELECT @json = JSON_MODIFY(
@json,
'append $',
JSON_QUERY(
CASE
WHEN [value.uuid] IS NOT NULL THEN (SELECT d.[field.uuid], [value.uuid] FOR JSON PATH, WITHOUT_ARRAY_WRAPPER)
WHEN [value] IS NOT NULL THEN (SELECT d.[field.uuid], [value] FOR JSON PATH, WITHOUT_ARRAY_WRAPPER)
END
)
)
FROM Data d
SELECT @json
结果:
[
{
"field":{
"uuid":"uuid-field-1"
},
"value":{
"uuid":"value-uuid"
}
},
{
"field":{
"uuid":"uuid-field-2"
},
"value":1
},
{
"field":{
"uuid":"uuid-field-3"
},
"value":3
},
{
"field":{
"uuid":"uuid-field-4"
},
"value":4
}
]
select
json_query((select v.[field.uuid] as 'uuid' for json path, without_array_wrapper)) as 'field',
value as 'value',
json_query((select v.[value.uuid] as 'uuid' where v.[value.uuid] is not null for json path, without_array_wrapper)) as 'value'
from
(
values
('uuid-field-1', 'value-uuid1', null),
('uuid-field-2', null, 2),
('uuid-field-3', 'value-uuid3', null),
('uuid-field-4', null, 4)
) as v([field.uuid], [value.uuid], value)
for json auto;--, without_array_wrapper;
我们正在探索 JSON feature in SQL Sever
,对于其中一个场景,我们想提出一个 SQL 可以 return 一个 JSON 如下
[
{
"field": {
"uuid": "uuid-field-1"
},
"value": {
"uuid": "uuid-value" //value is an object
}
},
{
"field": {
"uuid": "uuid-field-2"
},
"value": "1". //value is simple integer
}
... more rows
]
value
字段可以是简单的 integer/string 或嵌套对象。
我们可以想出一个 table 如下所示:
field.uuid | value.uuid | value|
------------|---------- | -----|
uuid-field-1| value-uuid | null |
uuid-field-2| null | 1 |
... more rows
但是一旦我们申请 for json path
,它就失败了
Property 'value' cannot be generated in JSON output due to a conflict with another column name or alias. Use different names and aliases for each column in SELECT list.
是否有可能以某种方式生成它?该值将在 value.uuid
或 value
中,而不是两者?
注意: 如果我们可以将每一行转换为单独的 JSON 并将它们全部添加到一个数组中,我们愿意接受这种可能性。
这个错误的原因是(如documentation中提到的)... FOR JSON PATH 子句使用列别名或列名来确定JSON 输出中的键名。如果别名包含点,则 PATH 选项会创建嵌套对象 。在您的情况下 value.uuid
和 value
都生成一个名称为 value
.
我可以推荐一种方法(可能不是最好的方法),它使用 JSON_MODIFY()
从一个空的 JSON 数组生成预期的 JSON:
Table:
CREATE TABLE Data (
[field.uuid] varchar(100),
[value.uuid] varchar(100),
[value] int
)
INSERT INTO Data
([field.uuid], [value.uuid], [value])
VALUES
('uuid-field-1', 'value-uuid', NULL),
('uuid-field-2', NULL, 1),
('uuid-field-3', NULL, 3),
('uuid-field-4', NULL, 4)
声明:
DECLARE @json nvarchar(max) = N'[]'
SELECT @json = JSON_MODIFY(
@json,
'append $',
JSON_QUERY(
CASE
WHEN [value.uuid] IS NOT NULL THEN (SELECT d.[field.uuid], [value.uuid] FOR JSON PATH, WITHOUT_ARRAY_WRAPPER)
WHEN [value] IS NOT NULL THEN (SELECT d.[field.uuid], [value] FOR JSON PATH, WITHOUT_ARRAY_WRAPPER)
END
)
)
FROM Data d
SELECT @json
结果:
[
{
"field":{
"uuid":"uuid-field-1"
},
"value":{
"uuid":"value-uuid"
}
},
{
"field":{
"uuid":"uuid-field-2"
},
"value":1
},
{
"field":{
"uuid":"uuid-field-3"
},
"value":3
},
{
"field":{
"uuid":"uuid-field-4"
},
"value":4
}
]
select
json_query((select v.[field.uuid] as 'uuid' for json path, without_array_wrapper)) as 'field',
value as 'value',
json_query((select v.[value.uuid] as 'uuid' where v.[value.uuid] is not null for json path, without_array_wrapper)) as 'value'
from
(
values
('uuid-field-1', 'value-uuid1', null),
('uuid-field-2', null, 2),
('uuid-field-3', 'value-uuid3', null),
('uuid-field-4', null, 4)
) as v([field.uuid], [value.uuid], value)
for json auto;--, without_array_wrapper;