如何为 NULL 子值保留一个空的 JSON 父对象 - SQL Server FOR JSON PATH

How to retain an empty JSON parent object for NULL child values - SQL Server FOR JSON PATH

我在问和回答我自己的问题,但我想看看是否还有其他人对如何执行此操作有更好的想法。

我有一些 JSON 要发送给第三方 API。我已经为我正在尝试做的事情创建了一个虚假的简化表示。 有一个 primary_selection 及其子元素和一个 secondary_selection 及其子元素。如果副选不存在,则子元素全部为NULL。根据 API,secondary_selection 是必需的,但可以为空。他们还希望排除 NULL 元素。

DECLARE @JSON_WITHOUT_NULLS NVARCHAR(500)
SELECT @JSON_WITHOUT_NULLS = (
    SELECT '123456' [administrative_info.account_num],
        '1' [administrative_info.user_id],
        'whole wheat bread' [primary_selection.vehicle_for_sauce],
        'avocado' [primary_selection.topping],
        'mayo' [primary_selection.sauce_type],
        NULL [secondary_selection.vehicle_for_mayo],
        NULL [secondary_selection.topping],
        NULL [secondary_selection.sauce_type]
        FOR JSON PATH, WITHOUT_ARRAY_WRAPPER
)
SELECT @JSON_WITHOUT_NULLS

上面的 SQL 产生以下结果:

"administrative_info": {
    account_num": "123456",
    "user_id": "1"
},
"primary_selection": {
    "vehicle_for_sauce": "whole wheat bread",
    "topping": "avocado",
    "sauce_type": "mayo"
}

但我想要的是:

"administrative_info": {
    "account_num": "123456",
    "user_id": "1"
},
"primary_selection": {
    "vehicle_for_sauce": "whole wheat bread",
    "topping": "avocado",
    "sauce_type": "mayo"
},
"secondary_selection": {}

所以,这是我的解决方案,但想看看是否还有其他人知道如何执行此操作。

    DECLARE @JSON_WITHOUT_NULLS NVARCHAR(500)

SELECT @JSON_WITHOUT_NULLS = (SELECT '123456' [administrative_info.account_num],
                                     '1' [administrative_info.user_id],
                                     'whole wheat bread' [primary_selection.vehicle_for_sauce],
                                     'avocado' [primary_selection.topping],
                                     'mayo' [primary_selection.sauce_type],
                                     NULL [secondary_selection.vehicle_for_mayo],
                                     NULL [secondary_selection.topping],
                                     NULL [secondary_selection.sauce_type]
                              FOR JSON PATH, WITHOUT_ARRAY_WRAPPER)

SELECT @JSON_WITHOUT_NULLS



DECLARE @EMPTY_OBJECT NVARCHAR(2) = '{}'
    SELECT @JSON_WITHOUT_NULLS = JSON_MODIFY(@JSON_WITHOUT_NULLS,'$.secondary_selection',JSON_QUERY(@EMPTY_OBJECT))

SELECT @JSON_WITHOUT_NULLS

另一种可能的选择是下面的语句。您需要使用 FOR JSON PATH.

生成每个一级 JSON 对象

请注意,您需要调用 JSON_QUERY() 以防止转义特殊字符。文档中对此进行了解释:JSON_QUERY return 是一个有效的 JSON 片段。因此,FOR JSON 不会转义 JSON_QUERY return 值中的特殊字符。如果您 return 使用 FOR JSON 计算结果,并且您要包括已经采用 JSON 格式的数据(在列中或作为表达式的结果),请将 JSON 数据 JSON_QUERY 没有路径参数 .

DECLARE @JSON_WITHOUT_NULLS NVARCHAR(max)
SELECT @JSON_WITHOUT_NULLS = (
   SELECT
      administrative_info = JSON_QUERY((
         SELECT '123456' [account_num], '1' [user_id]
         FOR JSON PATH, WITHOUT_ARRAY_WRAPPER
      )),
      primary_selection = JSON_QUERY((
         SELECT 'whole wheat bread' [vehicle_for_sauce], 'avocado' [topping], 'mayo' [sauce_type]
         FOR JSON PATH, WITHOUT_ARRAY_WRAPPER
      )),
      secondary_selection = JSON_QUERY((
         SELECT NULL [vehicle_for_mayo], NULL [topping], NULL [sauce_type]
         FOR JSON PATH, WITHOUT_ARRAY_WRAPPER
      ))
   FOR JSON PATH, WITHOUT_ARRAY_WRAPPER
)

结果:

{
   "administrative_info":{
      "account_num":"123456",
      "user_id":"1"
   },
   "primary_selection":{
      "vehicle_for_sauce":"whole wheat bread",
      "topping":"avocado",
      "sauce_type":"mayo"
   },
   "secondary_selection":{
      
   }
}