使用SQL提取嵌套的JSON

时间:2019-07-09 19:15:40

标签: json sql-server

我在检索JSON中的“ url”键的所有值时遇到麻烦

{  
   "vehicles":[  
      {  
         "vehicle":{  
            "media":{  
               "videos":[  

               ],
               "images":[  
                  {  
                     "url":"testURL1",
                     "position":1
                  },
                  {  
                     "url":"testURL2",
                     "position":2
                  }
               ],
               "imageCount":null,
               "merchandizedImages":null,
               "merchandizedImageCount":null,
               "fyuseIds":null
            }
         }
      },
      {  
         "vehicle":{  
            "media":{  
               "videos":[  

               ],
               "images":[  
                  {  
                     "url":"testingURL3",
                     "posiiton":"1"
                  },
                  {  
                     "url":"testingURL4",
                     "position":"2"
                  }
               ],
               "imageCount":null,
               "merchandizedImages":null,
               "merchandizedImageCount":null,
               "fyuseIds":null
            }
         }
      }
   ]
} 

我能够通过

来获取单个商品的价值
select @content = value from openjson(@json)
select [url] as imgURL
    from openjson(@content) 
    with (
        [url] nvarchar(max) '$.vehicle.media.images[0].url'
    )

但是我并不总是知道图像中的元素数量,也不知道车辆总数。

我可以使用

获取第一辆车的所有网址
select @content = value from openjson(@json)
    select @vehicle = vehicle from openjson(@content) with (vehicle nvarchar(max) as json)
    select @media = media from openjson(@vehicle) with (media nvarchar(max) as json)
    select @images = images from openjson(@media) with (images nvarchar(max) as json)
select [url] as imgURL
    from openjson(@images) 
    with (
        [url] nvarchar(max)
    )

但无法获得下一辆车,依此类推

2 个答案:

答案 0 :(得分:0)

总的来说(这也许是一种更好的方法),这是您所追求的吗?

SELECT u.[url],
       u.position
FROM OPENJSON(@JSON) 
     WITH (vehicles nvarchar(MAX) AS JSON) J
     CROSS APPLY OPENJSON(J.[vehicles]) 
                 WITH (vehicle nvarchar(MAX) '$.vehicle' AS JSON) v
     CROSS APPLY OPENJSON(v.vehicle)
                 WITH (media nvarchar(MAX) '$.media' AS JSON) m
     CROSS APPLY OPENJSON(m.media)
                 WITH (images nvarchar(MAX) '$.images' AS JSON) i
     CROSS APPLY OPENJSON(i.images)
                 WITH([url] nvarchar(MAX) '$.url',
                      position int '$.position') u;

请注意,'testingURL3'NULL返回了position,因为该节点不存在(它具有节点posiiton)。

如果不是,那么请问您在撒谎,我之前问过。

答案 1 :(得分:0)

对于初学者来说,您提供的JSON已完成。不仅您的键名拼写不同(例如position与posiiton),而且您的JSON无效,所以无论您做什么,都不会得到预期的结果。或更糟糕的是,您会得到结果,但结果却是错误的。

注意:您已对此进行了更正)

无论如何,这是您的JSON 应该的样子:

{"vehicles":[
  {"vehicle": {
      "media": {
        "videos":[],
        "images":[{ "url":"testingURL1", "position":"1" },{ "url": "testingURL2", "position":"2" }],
        "imageCount":4,
        "merchandizedImages":null,
        "merchandizedImageCount":null,
        "fyuseIds":null
      }
    }
  },
  {"vehicle": {
    "media": {  
      "videos":[],
      "images":[{ "url":"testingURL3", "position":"1" }, { "url":"testingURL4", "position":"2" }],
      "imageCount":4,
      "merchandizedImages":null,
      "merchandizedImageCount":null,
      "fyuseIds":null
    }
  }}
]}

一旦您的JSON是正确的,您就可以根据需要查询它。

以下是您可以在SSMS中运行的完整示例:

DECLARE @VehicleJSON VARCHAR(MAX) = '{"vehicles":[{"vehicle":{"media":{"videos":[],"images":[{"url":"testingURL1","position":"1"},{"url":"testingURL2","position":"2"}],"imageCount":4,"merchandizedImages":null,"merchandizedImageCount":null,"fyuseIds":null}}},{"vehicle":{"media":{"videos":[],"images":[{"url":"testingURL3","position":"1"},{"url":"testingURL4","position":"2"}],"imageCount":4,"merchandizedImages":null,"merchandizedImageCount":null,"fyuseIds":null}}}]}';

SELECT
    imageCount, merchandizedImages, merchandizedImageCount, fyuseIds, imageUrl, imagePosition
FROM OPENJSON( @VehicleJSON, '$.vehicles' )
WITH (
    imageCount INT '$.vehicle.media.imageCount',
    merchandizedImages VARCHAR(255) '$.vehicle.media.merchandizedImages',
    merchandizedImageCount INT '$.vehicle.media.merchandizedImageCount',
    fyuseIds VARCHAR(255) '$.vehicle.media.fyuseIds',
    Images NVARCHAR(MAX) '$.vehicle.media.images' AS JSON
) AS Vehicles
OUTER APPLY OPENJSON( Images )
WITH (
    imageUrl VARCHAR(255) '$.url',
    imagePosition INT '$.position'
);

哪个返回:

+------------+--------------------+------------------------+----------+-------------+---------------+
| imageCount | merchandizedImages | merchandizedImageCount | fyuseIds |  imageUrl   | imagePosition |
+------------+--------------------+------------------------+----------+-------------+---------------+
|          4 | NULL               | NULL                   | NULL     | testingURL1 |             1 |
|          4 | NULL               | NULL                   | NULL     | testingURL2 |             2 |
|          4 | NULL               | NULL                   | NULL     | testingURL3 |             1 |
|          4 | NULL               | NULL                   | NULL     | testingURL4 |             2 |
+------------+--------------------+------------------------+----------+-------------+---------------+

这应该使您朝着正确的方向前进。

此行的简短说明:

Images NVARCHAR(MAX) '$.vehicle.media.images' AS JSON

在这种情况下使用 AS JSON 时,数据类型必须为 NVARCHAR 。如果您另外定义,则会出现异常告诉您。