SQL Server 2017中的Json输出格式

时间:2019-01-11 19:58:32

标签: json sql-server

我在SQL Server 2017中有一个存储过程,该过程将结果集输出为JSON。它可以很好地输出设置,但是我希望使用其他格式。

根据MS文档,其发送的格式符合预期,但对我来说似乎违反直觉。无论如何我都不是JSON专家,但我一直认为它是结构的单个对象表示形式。

查询为:

SELECT 
    e.EventID AS 'Event.ID',
    EventDate AS 'Event.Date',
    ea.ActivityID AS 'Event.Activity.ID',
    ea.CreateDate AS 'Event.Activity.Date',
    ea.Notes AS 'Event.Activity.Notes'
FROM
    Events e  
JOIN 
    dbo.EventActivities ea ON e.EventID = ea.EventID
FOR JSON PATH

这将返回以下输出:

[
    {"Event":  { 
                   "ID":"236",
                   "Date":"2019-03-01",
                   "Activity": {"ID": 10,
                                "Date":"2019-01-02T11:47:33.2800000",
                                "Notes":"Event created"}
               }
    },
    {"Event": {
                  "ID":"236",
                  "Date":"2019-03-01",
                  "Activity": {"ID":20,
                               "Date":"2019-01-02T11:47:34.3933333",
                               "Notes":"Staff selected"}
              }
    },
    {"Event": {
                  "ID":"236",
                  "Date":"2019-03-01",
                  "Activity": {"ID":20,
                              "Date":"2019-01-02T11:47:34.3933333",
                              "Notes":"Staff selected"}
              }
     }
]

当我手动设置格式时(为了更好地显示它,它给我每个活动一个3个相同事件的数组。这与MS在Format Nested JSON中所说的一致

我期望(或更希望)看到类似的东西:

[
    {
        "Event": {
            "ID": "236",
            "Date": "2019-03-01",
            "Activity": [
                {
                    "ID": 10,
                    "Date": "2019-01-02T11:47:33.2800000",
                    "Notes": "Event created"
                },
                {
                    "ID": 20,
                    "Date": "2019-01-02T11:47:34.3933333",
                    "Notes": "Staff selected"
                },
                {
                    "ID": 20,
                    "Date": "2019-01-02T11:47:34.3933333",
                    "Notes": "Staff selected"
                }
            ]
        }
    }
]

是否可以得到这样的输出?还是无效?

2 个答案:

答案 0 :(得分:1)

首先,您可以使用ISJSON测试JSON字符串是否有效。您指示的预期输出未通过验证,但是接近。内部数组缺少“ []”。

但是,我知道您的处理方法。为了更好地解释我认为您遇到的问题是什么,我将美化查询中输出JSON的格式以匹配您期望的JSON。

原始输出如下:

[
    {"Event":
        {"ID":"236","Date":"2019-03-01",
            "Activity":{
                "ID":10,"Date":"2019-01-02T11:47:33.2800000","Notes":"Event created"
            }
        }
    },
    {"Event":
        {"ID":"236","Date":"2019-03-01",
            "Activity":{
                "ID":20,"Date":"2019-01-02T11:47:34.3933333","Notes":"Staff selected"}
        }
    },
    {"Event":
        {"ID":"236","Date":"2019-03-01",
            "Activity":{
                "ID":20,"Date":"2019-01-02T11:47:34.3933333","Notes":"Staff selected"
            }
        }
    }
]

根据您的理想格式,可能的有效JSON字符串如下:

{"Event":
    [
        {"ID":236,"Date":"2019-03-01",
            "Activity":
                [
                    {"ID":10,"Date":"2019-01-02T11:47:33.2800000","Notes":"Event created"},
                    {"ID":20,"Date":"2019-01-02T11:47:34.3933333","Notes":"Staff selected"},
                    {"ID":20,"Date":"2019-01-02T11:47:34.3933333","Notes":"Staff selected"}
                ]
        }
    ]
}

您可以通过调整第二个表的表别名并使用FOR JSON AUTOROOT来实现。它将返回其每个“ EventActivities”都没有重复的“ Event”属性的输出。对于每个“事件”,它将其相关的“ EventActivities”放入数组中。

以下SQL将返回所需的输出:

SELECT [Event].EventID AS 'ID',
    [Event].EventDate AS 'Date',
    Activity.ActivityID AS 'ID',
    Activity.CreateDate AS 'Date',
    Activity.Notes AS 'Notes'
FROM #Events [Event]
JOIN #EventActivities Activity
    ON [Event].EventID = Activity.EventID
FOR JSON AUTO, ROOT('Event')

确切的输出如下:

{"Event":[{"ID":236,"Date":"2019-03-01","Activity":[{"ID":10,"Date":"2019-01-02T11:47:33.2800000Z","Notes":"Event created"},{"ID":20,"Date":"2019-01-02T11:47:33.2800000Z","Notes":"Staff selected"},{"ID":20,"Date":"2019-01-02T11:47:33.2800000Z","Notes":"Staff selected"}]}]}

它不会以美化的格式返回,但是可以添加空格和缩进,而不会损害它是有效JSON的事实,同时还可以达到预期的数组要求。

答案 1 :(得分:0)

您的预期输出不是有效的JSON。但是,假设您将“活动”字段引用为活动数组,则可以使用嵌套查询。

SELECT
    E.EventID AS 'Event.ID',
    E.EventDate AS 'Event.Date',
    (
        SELECT
            A.ActivityID AS 'ID',
            A.CreateDate AS 'Date',
            A.Notes AS 'Notes'
        FROM dbo.EventActivities AS A
        WHERE A.EventID = E.EventID
        FOR JSON PATH
    ) AS 'Event.Activities'
FROM dbo.Events AS E
FOR JSON PATH