sql - Json_value 和 Json_query 找不到指定的路径

标签 sql json sql-server tsql

我正在尝试解析来自以下 JSON 的数据。我知道 JSON_VALUE 和 JSON_QUERY 之间存在差异,但我只是想使路径结构正确。我正在使用 STRICT 选项来验证我的路径,到目前为止,除了 string$ 之外,对于 JSON 查询,一切都因找不到路径而失败。一旦我添加 .data.taskData 路径似乎就爆炸了。任何帮助将不胜感激。

我正在将以下 JSON 设置为 @json

declare @json nvarchar(max)
SELECT JSON_VALUE(@json, 'strict$.data.taskData.startedLocation') as json 
select JSON_QUERY(@json, 'strict$.data.taskData.startedLocation')  as json

下面是我要解析的 JSON

{"data.taskData":{"startedAtUtc":"2019-08-28T20:21:29.025Z","startedLocation":{"lat":60.7348366,"lon":-124.9856841},"additionalData":[],"bols":[{"number":"1234","product":{"id":"COFFEE","description":"GROUND COFFE 5LB CAN","plannedQuantity":1352,"uom":"PCS","supplier":"WALMART ","accountOf":"","class":"UNKNOWN","loadedQuantity":6600,"netQuantity":9993},"net":"9993"}],"compartments":[{"id":"1","capacity":3400,"commodity":null,"consignee":"KSUAC","plannedQuantity":0,"tankID":"1","additionalData":[],"allLoadsValid":true,"complete":true,"error":false,"locked":false,"loads":[{"isFirst":true,"quantity":"1000","bol":"1234"}],"loadedQuantity":1000,"productID":"COFFEE"},{"id":"2","capacity":2000,"commodity":null,"consignee":"KSUAC","plannedQuantity":0,"tankID":"2","additionalData":[],"allLoadsValid":true,"complete":true,"error":false,"locked":false,"loads":[{"isFirst":true,"quantity":"2000","bol":"1234"}],"loadedQuantity":2000,"productID":"COFFEE"},{"id":"3","capacity":1100,"commodity":null,"consignee":"KSUAC","plannedQuantity":0,"tankID":"3","additionalData":[],"allLoadsValid":true,"complete":true,"error":false,"locked":false,"loads":[{"isFirst":true,"quantity":"1100","bol":"1234"}],"loadedQuantity":1100,"productID":"COFFEE"},{"id":"4","capacity":2700,"commodity":null,"consignee":null,"plannedQuantity":0,"tankID":"4","additionalData":[],"allLoadsValid":true,"complete":true,"error":false,"locked":false,"loads":[{"isFirst":true,"quantity":"2500","bol":"1234"}],"loadedQuantity":2500,"productID":"COFFEE"}],"detention":{"minutes":null,"reasonCode":null,"notes":null},"initialCompartments":[{"id":"1","capacity":3400,"commodity":null,"consignee":null,"plannedQuantity":null,"tankID":"1"},{"id":"2","capacity":2000,"commodity":null,"consignee":null,"plannedQuantity":null,"tankID":"2"},{"id":"3","capacity":1100,"commodity":null,"consignee":null,"plannedQuantity":null,"tankID":"3"},{"id":"4","capacity":2700,"commodity":null,"consignee":null,"plannedQuantity":null,"tankID":"4"}],"loadingComplete":"yes","loadingCompleteTime":"2019-08-28T20:23:05.453Z","uom":{"key":"PCS","category":"volume","shortDisplay":"p","longDisplay":"Pieces","conversionFactors":{"gal":0.0625,"L":0.2365882365,"c":4.2267528377}},"variances":[],"completedAtUtc":"2019-08-28T20:23:06.703Z","completedLocation":{"lat":61.7348308,"lon":-124.9856879},"finalCompartments":[{"id":"1","capacity":3400,"productID":"COFFEE","loadedQuantity":1000,"consignee":"KSUAC","tankID":"1"},{"id":"2","capacity":2000,"productID":"COFFEE","loadedQuantity":2000,"consignee":"KSUAC","tankID":"2"},{"id":"3","capacity":1100,"productID":"COFFEE","loadedQuantity":1100,"consignee":"KSUAC","tankID":"3"},{"id":"4","capacity":2700,"productID":"COFFEE","loadedQuantity":2500,"consignee":null,"tankID":"4"}]}}

最佳答案

试试这个。在代码之后我将评论特色:

DECLARE @json NVARCHAR(MAX)=N'{
    "data.taskData": {
        "startedAtUtc": "2019-08-28T20:21:29.025Z",
        "startedLocation": {
            "lat": 60.7348366,
            "lon": -124.9856841
        },
        "additionalData": [],
        "bols": [
            {
                "number": "1234",
                "product": {
                    "id": "COFFEE",
                    "description": "GROUND COFFE 5LB CAN",
                    "plannedQuantity": 1352,
                    "uom": "PCS",
                    "supplier": "WALMART ",
                    "accountOf": "",
                    "class": "UNKNOWN",
                    "loadedQuantity": 6600,
                    "netQuantity": 9993
                },
                "net": "9993"
            }
        ],
        "compartments": [
            {
                "id": "1",
                "capacity": 3400,
                "commodity": null,
                "consignee": "KSUAC",
                "plannedQuantity": 0,
                "tankID": "1",
                "additionalData": [],
                "allLoadsValid": true,
                "complete": true,
                "error": false,
                "locked": false,
                "loads": [
                    {
                        "isFirst": true,
                        "quantity": "1000",
                        "bol": "1234"
                    }
                ],
                "loadedQuantity": 1000,
                "productID": "COFFEE"
            },
            {
                "id": "2",
                "capacity": 2000,
                "commodity": null,
                "consignee": "KSUAC",
                "plannedQuantity": 0,
                "tankID": "2",
                "additionalData": [],
                "allLoadsValid": true,
                "complete": true,
                "error": false,
                "locked": false,
                "loads": [
                    {
                        "isFirst": true,
                        "quantity": "2000",
                        "bol": "1234"
                    }
                ],
                "loadedQuantity": 2000,
                "productID": "COFFEE"
            },
            {
                "id": "3",
                "capacity": 1100,
                "commodity": null,
                "consignee": "KSUAC",
                "plannedQuantity": 0,
                "tankID": "3",
                "additionalData": [],
                "allLoadsValid": true,
                "complete": true,
                "error": false,
                "locked": false,
                "loads": [
                    {
                        "isFirst": true,
                        "quantity": "1100",
                        "bol": "1234"
                    }
                ],
                "loadedQuantity": 1100,
                "productID": "COFFEE"
            },
            {
                "id": "4",
                "capacity": 2700,
                "commodity": null,
                "consignee": null,
                "plannedQuantity": 0,
                "tankID": "4",
                "additionalData": [],
                "allLoadsValid": true,
                "complete": true,
                "error": false,
                "locked": false,
                "loads": [
                    {
                        "isFirst": true,
                        "quantity": "2500",
                        "bol": "1234"
                    }
                ],
                "loadedQuantity": 2500,
                "productID": "COFFEE"
            }
        ],
        "detention": {
            "minutes": null,
            "reasonCode": null,
            "notes": null
        },
        "initialCompartments": [
            {
                "id": "1",
                "capacity": 3400,
                "commodity": null,
                "consignee": null,
                "plannedQuantity": null,
                "tankID": "1"
            },
            {
                "id": "2",
                "capacity": 2000,
                "commodity": null,
                "consignee": null,
                "plannedQuantity": null,
                "tankID": "2"
            },
            {
                "id": "3",
                "capacity": 1100,
                "commodity": null,
                "consignee": null,
                "plannedQuantity": null,
                "tankID": "3"
            },
            {
                "id": "4",
                "capacity": 2700,
                "commodity": null,
                "consignee": null,
                "plannedQuantity": null,
                "tankID": "4"
            }
        ],
        "loadingComplete": "yes",
        "loadingCompleteTime": "2019-08-28T20:23:05.453Z",
        "uom": {
            "key": "PCS",
            "category": "volume",
            "shortDisplay": "p",
            "longDisplay": "Pieces",
            "conversionFactors": {
                "gal": 0.0625,
                "L": 0.2365882365,
                "c": 4.2267528377
            }
        },
        "variances": [],
        "completedAtUtc": "2019-08-28T20:23:06.703Z",
        "completedLocation": {
            "lat": 61.7348308,
            "lon": -124.9856879
        },
        "finalCompartments": [
            {
                "id": "1",
                "capacity": 3400,
                "productID": "COFFEE",
                "loadedQuantity": 1000,
                "consignee": "KSUAC",
                "tankID": "1"
            },
            {
                "id": "2",
                "capacity": 2000,
                "productID": "COFFEE",
                "loadedQuantity": 2000,
                "consignee": "KSUAC",
                "tankID": "2"
            },
            {
                "id": "3",
                "capacity": 1100,
                "productID": "COFFEE",
                "loadedQuantity": 1100,
                "consignee": "KSUAC",
                "tankID": "3"
            },
            {
                "id": "4",
                "capacity": 2700,
                "productID": "COFFEE",
                "loadedQuantity": 2500,
                "consignee": null,
                "tankID": "4"
            }
        ]
    }
}';

--查询

SELECT FirstLevel.StartedAtUtc
      ,JSON_VALUE(FirstLevel.startedLocation,'$.lat') AS startedLocation_Lat
      ,JSON_VALUE(FirstLevel.startedLocation,'$.lon') AS startedLocation_Lon
      ,FirstLevel.additionalData
      ,FirstLevel.bols
      ,Sub_Compartments.id
      ,Sub_Compartments.capacity
      ,FirstLevel.loadingComplete
FROM OPENJSON(@json,'$."data.taskData"')
WITH(startedAtUtc DATETIME2
    ,startedLocation NVARCHAR(MAX) AS JSON
    ,additionalData NVARCHAR(MAX) AS JSON
    ,bols NVARCHAR(MAX) AS JSON
    --compartments seems to be a 1:n related node
    ,compartments NVARCHAR(MAX) AS JSON
    ,loadingComplete NVARCHAR(10)
    --and more
    ) FirstLevel
OUTER APPLY OPENJSON(FirstLevel.compartments)
WITH (id INT
     ,capacity INT
     --more columns
     ) Sub_Compartments;

简而言之:

您的 JSON 是一个完全成熟的深层嵌套结构,包含各种数据。返回整体和所有会导致非常多余的平面表。使用尽可能窄的问题查询此 JSON 是个好主意。

正如您已经被告知的,我们可以使用其中之一:

  • JSON_VALUE() 从给定路径检索标量值。嵌套的 JSON 将作为字符串类型返回。
  • JSON_QUERY() 用于提取 JSON 片段并将其作为 JSON 处理
  • 需要 OPENJSON 来深入研究具有重复元素的 JSON,以便将片段作为派生集逐行返回。非常重要的是 WITH 子句,它允许将 OPENJSON 的默认输出更改为列的并排(类似于 PIVOT)。

在这种情况下,我们可以使用 OPENJSON 深入到第一层并返回在那里找到的对象。其中一些是标量值,可以作为类型值返回,其他是 JSON 对象。在这种情况下,我们必须使用 NVARCHAR(MAX) 作为数据类型,并且必须将 sepcify AS JSON 以便继续处理返回值。

在您的 JSON 中,隔间是 1:n 相关集。我们可以使用级联的 OPENJSON 调用,使用第一个返回的片段作为输入,并使用另一个 WITH 子句来提取隔间的列。

我希望这个例子能给你足够的提示,让你可以查询 JSON 的任何地方。祝你好运!

关于sql - Json_value 和 Json_query 找不到指定的路径,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57778767/

相关文章:

ios - 将 JSON 响应与字符串进行比较

sql-server - 在 sp_executesql 中使用 LIKE

.net - 在哪里/如何存储 SQL Server 连接字符串,以便远程应用程序可以安全地使用它?

mysql - 将列值组合在一个单元格中

java - 有没有一个规范的例子说明如何使用 Antlr 4 来解析 SQL 语句?

ios - Swift 3 无法使用 SwiftyJSON 和 Alamofire 下标类型为 'String' 的值和类型为 'String' 的索引

sql-server - 如何防止使用此 UNION 选择(或其他方法)重复

sql - 为什么 SQL Server 的 OBJECT_ID(NVARCHAR) 不带变量?

sql - 是否可以在同一查询中同时使用过滤器和 View 函数?

java - 使用 Jackson 解析数组