TSQL JSON如何将数组添加到现有的Json对象?

时间:2019-07-11 11:34:05

标签: json tsql

我们有一个SQL查询,其中我们使用JSON Path创建一个JSON文件。 我们想将2个JSON对象合并为1个JSON。但是我们在代码中很难完成这项任务。

我们尝试使用JSON_MODIFY将它们合并在一起。但这对我们不起作用。

我们想做的是,我们有2个独立的json对象,我们想将它们合并为一个。

Json对象A:

{
    "ID" : 0,
    "Name" : "a name",
    "Description" : "a description"
}

和Json对象B

"Nodes" : [
    {
        "NodeID" : 10,
        "NodeName" : "Node 0"
    },
    {
        "NodeID" : 11,
        "NodeName" : "Node 1"
    }
]

我们想要拥有的东西:

{
    "ID" : 0,
    "Name" : "a name",
    "Description" : "a description",
    "Nodes" : [
        {
            "NodeID" : 10,
            "NodeName" : "Node 0"
        },
        {
            "NodeID" : 11,
            "NodeName" : "Node 1"
        }
    ]
}

我们当前的SQL查询如下:

set @JsonCourse = ( select c.name, c.id, c.description from dbo.courses c where c.id = @id for json path)

set @JsonNodes = ( select n.id, n.name from dbo.nodes n where n.courseId = @id for json path, root('Nodes'))

set @CompleteJson =  JSON_MODIFY(@JsonCourse,'append $',JSON_QUERY(@JsonNodes));

print @CompleteJson

但是我们的结果是这样的:

[
    {
        "ID" : 0,
        "Name" : "a name",
        "Description" : "a description" 
    },
    {
        "Nodes" : [
            {
                "NodeID" : 10,
                "NodeName" : "Node 0"
            },
            {
                "NodeID" : 11,
                "NodeName" : "Node 1"
            }
        ]
    }
]

注意:我们在这里使用了假设数据。

我们如何使用JSON_MODIFY修复此问题?

2 个答案:

答案 0 :(得分:0)

请阅读有关creating a MCVE的信息。这是一个独立示例,可以使您的问题重现,并帮助我们提供简单的答案...

如果我正确理解了这一点,则存在一个1:n相关的结构,其中“对象A”中的每个节点可以在“对象B”中具有多个节点。

我的以下代码将通过INFORMATION_SCHEMA对此进行模拟。每个表为1或许多列。

我们用相关子查询解决了这个问题。这是创建嵌套JSON数组的方法:

SELECT TOP 3 t.TABLE_NAME AS NodeName
            ,t.TABLE_TYPE AS NodeType
            ,(
                SELECT TOP 3 c.COLUMN_NAME AS ColumnName
                            ,c.DATA_TYPE AS ColumnType 
                FROM INFORMATION_SCHEMA.COLUMNS c 
                WHERE c.TABLE_CATALOG=t.TABLE_CATALOG
                 AND  c.TABLE_SCHEMA=t.TABLE_SCHEMA
                 AND  c.TABLE_NAME=t.TABLE_NAME
                FOR JSON PATH
             ) AS MyColumns
FROM INFORMATION_SCHEMA.TABLES t
FOR JSON PATH;

结果

[
    {
        "NodeName": "spt_fallback_db",
        "NodeType": "BASE TABLE",
        "MyColumns": [
            {
                "ColumnName": "xserver_name",
                "ColumnType": "varchar"
            },
            {
                "ColumnName": "xdttm_ins",
                "ColumnType": "datetime"
            },
            {
                "ColumnName": "xdttm_last_ins_upd",
                "ColumnType": "datetime"
            }
        ]
    },
    {
        "NodeName": "spt_fallback_dev",
        "NodeType": "BASE TABLE",
        "MyColumns": [
            {
                "ColumnName": "xserver_name",
                "ColumnType": "varchar"
            },
            {
                "ColumnName": "xdttm_ins",
                "ColumnType": "datetime"
            },
            {
                "ColumnName": "xdttm_last_ins_upd",
                "ColumnType": "datetime"
            }
        ]
    },
    {
        "NodeName": "spt_fallback_usg",
        "NodeType": "BASE TABLE",
        "MyColumns": [
            {
                "ColumnName": "xserver_name",
                "ColumnType": "varchar"
            },
            {
                "ColumnName": "xdttm_ins",
                "ColumnType": "datetime"
            },
            {
                "ColumnName": "xdttm_last_ins_upd",
                "ColumnType": "datetime"
            }
        ]
    }
]

如您所见,每个表都是一组嵌套的列,通过JSON数组表示。

答案 1 :(得分:0)

因此,我将添加另一个答案,因为这与第一个答案完全不同:

由于我没有您的表,因此将JSON变量设置为您提供的值

DECLARE @json1 NVARCHAR(MAX)=
N'{
    "ID" : 0,
    "Name" : "a name",
    "Description" : "a description"
}'

DECLARE @json2 NVARCHAR(MAX)= --<-- had to add the surrounding {}, otherwise this was invalid JSON
N'{"Nodes" : 
[
    {
        "NodeID" : 10,
        "NodeName" : "Node 0"
    },
    {
        "NodeID" : 11,
        "NodeName" : "Node 1"
    }
]}';

-我们在这里不需要append
-我们必须告诉引擎新节点的名称。
-为避免重复输入键Nodes,我使用@json2作为路径从$.Nodes读取

DECLARE @CompleteJSON NVARCHAR(MAX)=JSON_MODIFY(@Json1,'$.Nodes',JSON_QUERY(@Json2,'$.Nodes'));

PRINT @CompleteJSON;

我希望这更接近您的需求...