正在从 SQL 服务器解析 JSON

Parsing JSON from SQL Server

我有一个包含以下列的 table,其中一列是 JSON blob。我不清楚如何将 JSON blob 解析为与其他列并排的一系列列。我知道有一个叫做 OPENJSON 的东西,但不确定如何将它应用到这种情况下。

ID  |   ORGANIZATION   |  DEVICE_TIME  |   DEVICE   |     DATA 
--------------------------------------------------------------------  
011        015             2021-07-20       015        (JSON COLUMN)
012        016             2021-08-20       016        (JSON COLUMN)

下面是 json 字符串示例,来自上面的 DATA

{
    "device":   {
        "battery_level":    98,
        "rssi": -105,
        "boot_cnt": 5,
        "apn":  "teal",
        "ip_addr":  "10.176.30.171",
        "fw_ver":   "1.00",
        "modem_fw": "mfw_nrf9160_1.3.0",
        "imsi": "234500024531391",
        "imei": "352656101040510",
        "iccid":    "8901990000000534985"
    },
     "data":    {
       "Temperature":   77.563942718505871,
       "Humidity":  29.100597381591797,
       "pressure":  28.883883226248145,
       "air_quality":   37.067466735839844,
       "SoilMoisture":  0.42462845010615713,
       "Lat":   0,
       "Long":  0,
       "Alt":   0
    }
}

openjson returns a table(可能有很多行,虽然不是你的样本)。

要将某些内容放入列中,您需要一个标量。试试这个例子。是的,您需要明确列出列。

/* Create a sample table */
WITH MySampleTable
AS (
SELECT 1 as col1, 2 as col2, 'Hi There' as col3,
CAST('
{
    "device":   {
        "battery_level":    98,
        "rssi": -105,
        "boot_cnt": 5,
        "apn":  "teal",
        "ip_addr":  "10.176.30.171",
        "fw_ver":   "1.00",
        "modem_fw": "mfw_nrf9160_1.3.0",
        "imsi": "234500024531391",
        "imei": "352656101040510",
        "iccid":    "8901990000000534985"
    },
     "data":    {
       "Temperature":   77.563942718505871,
       "Humidity":  29.100597381591797,
       "pressure":  28.883883226248145,
       "air_quality":   37.067466735839844,
       "SoilMoisture":  0.42462845010615713,
       "Lat":   0,
       "Long":  0,
       "Alt":   0
    }
}
'
AS NVARCHAR(MAX)
) as myjsoncolumn
UNION ALL
SELECT 5,6,'Test','
{
    "device":   {
        "battery_level":    2,
        "rssi": -105,
        "boot_cnt": 5,
        "apn":  "teal"
    },
     "data":    {
       "Humidity":  29.100597381591797,
       "pressure":  28.883883226248145
    }
}
'
)

SELECT *, 
JSON_VALUE(myjsoncolumn,'$.device.battery_level') as battery_level,
JSON_VALUE(myjsoncolumn,'$.data.Temperature') as Temp
FROM MySampleTable

语句通常取决于解析的JSON数据的结构。在这种情况下,一个可能的选项是 OPENJSON() 具有显式模式(带有列定义的 WITH 子句),使用适当的数据类型和 path 表达式:

JSON 和 table:

DECLARE @json varchar(max) = '{
    "device":   {
        "battery_level":    98,
        "rssi": -105,
        "boot_cnt": 5,
        "apn":  "teal",
        "ip_addr":  "10.176.30.171",
        "fw_ver":   "1.00",
        "modem_fw": "mfw_nrf9160_1.3.0",
        "imsi": "234500024531391",
        "imei": "352656101040510",
        "iccid":    "8901990000000534985"
    },
     "data":    {
       "Temperature":   77.563942718505871,
       "Humidity":  29.100597381591797,
       "pressure":  28.883883226248145,
       "air_quality":   37.067466735839844,
       "SoilMoisture":  0.42462845010615713,
       "Lat":   0,
       "Long":  0,
       "Alt":   0
    }
}'
SELECT *
INTO Data
FROM (VALUES
   ('011', '015', '2021-07-20', '015', @json),
   ('012', '016', '2021-08-20', '016', @json)
) v (ID, ORGANIZATION, DEVICE_TIME, DEVICE, DATA)

声明:

SELECT d.*, j.*
FROM Data d
OUTER APPLY OPENJSON(d.DATA) WITH (
   batery_level int '$.device.battery_level',
   rssi int '$.device.rssi',
   boot_cnt int '$.device.boot_cnt',
   apn varchar(10) '$.device.boot_apn',
   ip_addr varchar(19) '$.device.ip_addr',
   fw_ver varchar(5) '$.device.fw_ver',
   modem_fw varchar(59) '$.device.modem_fw',
   imsi varchar(15) '$.device.imsi',
   imei varchar(15) '$.device.imei',
   iccid varchar(50) '$.device.iccid',
   Temperature numeric(20, 15) '$.data.Temperature',
   Humidity numeric(22, 18) '$.data.Humidity',
   pressure numeric(22, 18) '$.data.pressure',
   air_quality numeric(22, 18) '$.data.air_quality',
   SoilMoisture numeric(22, 18) '$.data.SoilMoisture',
   Lat numeric(9, 6) '$.data.Lat',
   Long numeric(9, 6) '$.data.Long',
   Alt numeric(9, 6) '$.data.Alt'
) j