簡體   English   中英

解析JSON數據並插入MySQL

[英]Parsing JSON data and inserting to MySQL

因此,基本上我想在PHP中解析JSON文件並將數據插入特定的表/列。 目前,我有一個有效的腳本,但需要我對其進行大量修改,直到它起作用為止。 但是,由於我正在收集的JSON數據的大小可能會有所不同,因此會有更多的數據行,因此它最終將無法工作。

JSON文件的結構與我所見過的大多數不同。 可能是因為其輸出數據來自傳感器單元。 我想將數據和序列號插入數據表中,並有一個error_log表,可以在其中將序列號和錯誤消息存儲為字符串。 我該如何實現?

JSON檔案:

{
   "device": {
      "sn": 5165654,
      "name": "FDI_AWS_DEMO",
      "v": "2.7B3"
   },
   "channels": [
      {
         "code": "RH",
         "name": "Relative Humidity",
         "unit": "%"
      },
      {
         "code": "AT",
         "name": "Air Temperature",
         "unit": "C"
      },
      {
         "code": "MINVi",
         "name": "Min voltage",
         "unit": "V"
      },
      {
         "code": "PTi",
         "name": "Processor temperature",
         "unit": "C"
      },
      {
         "code": "SDB",
         "name": "Network signal dB",
         "unit": "dB"
      },
      {
         "code": "LWS",
         "name": "Leaf Wetness",
         "unit": "%"
      },
      {
         "code": "WSAV",
         "name": "Wind Speed Avg",
         "unit": "km/h"
      },
      {
         "code": "WSMX",
         "name": "Wind Speed Max",
         "unit": "km/h"
      },
      {
         "code": "WSMN",
         "name": "Wind Speed Min",
         "unit": "km/h"
      },
      {
         "code": "PR_TOT",
         "name": "PR Tot",
         "unit": "mm"
      },
      {
         "code": "RAIN",
         "name": "Rain",
         "unit": "mm"
      },
      {
         "code": "FDI",
         "name": "fdi",
         "unit": "Unit"
      },
      {
         "code": "DT",
         "name": "Delta-T",
         "unit": "C"
      },
      {
         "code": "LAT",
         "name": "Latitude",
         "unit": "deg"
      },
      {
         "code": "LON",
         "name": "Longitude",
         "unit": "deg"
      },
      {
         "code": "WD",
         "name": "Wind Direction",
         "unit": "Degrees"
      },
      {
         "code": "P1",
         "name": "Par1",
         "unit": ""
      },
      {
         "code": "AVGCi",
         "name": "Average Current",
         "unit": "mA"
      },
      {}
   ],
   "data": [
      {
         "$ts": 170801164400,
         "$msg": "SD_FAIL;1"
      },
      {
         "$ts": 170801170000,
         "$msg": "WDT;WV01"
      },
      {
         "$ts": 170801170000,
         "$msg": "WDT;SDI12"
      },
      {
         "$ts": 170801170000,
         "$msg": "WDT;LWS"
      },
      {
         "$ts": 170801170000,
         "RH": 67.15,
         "AT": 12.87,
         "MINVi": 3.81,
         "PTi": 23.4,
         "LWS": "0*T",
         "WSAV": 0,
         "WSMX": 0,
         "WSMN": 0,
         "PR_TOT": 156,
         "RAIN": 0,
         "FDI": 0.239,
         "DT": 2.881,
         "WD": "0*T",
         "P1": "0*T",
         "AVGCi": 175
      },
      {}
   ]
}

PHP代碼:

<?php
    //connect to mysql db
    $myConnection= mysqli_connect("localhost","root","******", "ii") or die ("could not connect to mysql"); 

    //read the json file contents
    $jsondata = file_get_contents('test.json');

    //convert json object to php associative array
    $data = json_decode($jsondata, true);

    $id = $data['device']['sn'];
    $ts = $data['data']['$ts'];
    $RH = $data['data']['RH'];
    $AT = $data['data']['AT'];
    $MINVi = $data['data']['MINVi'];
    $PTi = $data['data']['PTi'];
    $SDB = $data['data']['SDB'];
    $LWS = $data['data']['LWS'];
    $WSAV = $data['data']['WSAV'];
    $WSMX = $data['data']['WSMX'];
    $WSMN = $data['data']['WSMN'];
    $PR_TOT = $data['data']['PR_TOT'];
    $RAIN = $data['data']['RAIN'];
    $FDI = $data['data']['FDI'];
    $DT = $data['data']['DT'];
    $LAT = $data['data']['LAT'];
    $LON = $data['data']['LON'];
    $WD = $data['data']['WD'];
    $P1 = $data['data']['P1'];
    $AVGCi = $data['data']['AVGCi'];



    //insert into mysql table
    $sql = "INSERT INTO test(sn, date, RH, AT, MINVi, PTi, SDB, LWS, WSAV, WSMX, WSMN, PR_TOT, RAIN, FDI, DT, LAT, LON, WD, P1, AVGCi)
    VALUES('$id', '$ts', '$RH','$AT', '$MINVi', '$PTi', '$SDB', '$LWS', '$WSAV', '$WSMX', '$WSMN', '$PR_TOT', '$RAIN', '$FDI', '$DT', '$LAT', '$LON', '$WD', '$P1', '$AVGCi')";


 $query=mysqli_query($myConnection, $sql) or die(mysqli_error($myConnection)); 
?>

測試數據表和error_log表

表格截圖

JSON數組var_dump- JSON var dump

任何幫助都會很棒

(獲得基本要點后,我想合並PDO)

  1. 不要盲目地將json轉換為關聯數組。 它帶來了更多的問題。
  2. 要訪問包含特殊字符或保留字的屬性,請使用占位符,例如$data->{'$ts'}
  3. 如果需要,遍歷數組和對象。
  4. 在表中添加自動增量id列有助於存儲一台設備的數據。
  5. 最好也將time添加到error_log表中

經過測試的原始問題的波紋管短版,可以正常工作。

<?php
        $_user = 'root';
        $_password= 'root';
        $_db = 'localtest';
        $_host = 'localhost';
        $_port = 3306;
    $con = new mysqli($_host, $_user, $_password, $_db) or die(mysql_error);

    //read the json file contents
    $jsondata = file_get_contents('test.json');

    //do not convert to array
    $json = json_decode($jsondata);

    $id = $json->device->sn;
    foreach($json->data as $key => $data){
        if(empty($data) || !isset($data->{'$ts'})){
            continue;
        }
        if (isset($data->{'$msg'})){
            $msg = $data->{'$msg'};
            $time = $data->{'$ts'};

            $sql="INSERT into error_log (sn, time, MSG) VALUES (?,?,?); ";
            $stmt = $con-> prepare($sql);
            $stmt -> bind_param("iss", $id,$time, $msg);
            $stmt -> execute();
        }else{
            $time = (isset($data->{'$ts'}))? $data->{'$ts'}:'';
            $RH = (isset($data->RH))? $data->RH:'';
            $AT = (isset($data->AT))? $data->AT:'';
            $MINVi = (isset($data->MINVi))? $data->MINVi:'';

            //insert into mysql table
            $sql="INSERT into test (sn, date, RH, AT, MINVi) VALUES (?,?,?,?,?); ";
            $stmt = $con-> prepare($sql);
            $stmt -> bind_param("issss", $id,$time,$RH,$AT,$MINVi);
            $stmt -> execute();
        }


    }
    mysqli_close($con);

?>

看起來json解碼正在將數組變成一個基於對象的數組...通過下面的函數運行$ data可以將它變成更多的關系數組,該數組以您嘗試讀取的方式進行設置...。

我現在找不到我為此擁有的功能,但是如果您更像這樣閱讀數組:

$newvar = $data->node;

//to echo this try this...
echo '<pre style="text-align:left;">';
print_r($data);
echo '</pre>';

或嘗試使用php的fb日志查看ya瀏覽器控制台中的數組-使用firephp作為插件。

它應該工作正常...

希望能有所幫助。

也許這樣的事情可以使您步入正軌……我注意到的一件事是,給定的JSON數據(FYI)中似乎沒有SDB條目。

<?php
//connect to mysql db
$myConnection= mysqli_connect("localhost","root","******", "ii") or die ("could not connect to mysql"); 

//read the json file contents
$jsondata = file_get_contents('test.json');

//convert json object to php associative array
$data = json_decode($jsondata, true);

// Make sure $data has values
if (empty($data)) {
  // Process error here
}
else {
  // Make sure the proper keys have been set
  if (!(isset($data['device']) && !empty($data['device']) && isset($data['data']) && !empty($data['data']))) {
    // Process error here if not set
  }
  // If so, make sure the sn key has been set
  elseif (!isset($data['device']['sn']) || empty($data['device']['sn'])) {
    // Process error here if not set
  }
  else {        
    $data_arr = $data['data'];

    foreach ($data_arr as $key => $arr) {
      // Iterate through for loop
      for ($i = 0; $i < count($data_arr); $i++) {
        // Make sure every single key is set
        if (!(isset($data_arr[$i]['$ts']) && isset($data_arr[$i]['RH']) && isset($data_arr[$i]['AT']) && isset($data_arr[$i]['MINVi']) && isset($data_arr[$i]['PTi']) && isset($data_arr[$i]['SDB']) && isset($data_arr[$i]['LWS']) && isset($data_arr[$i]['WSAV']) && isset($data_arr[$i]['WSMX']) && isset($data_arr[$i]['WSMN']) && isset($data_arr[$i]['PR_TOT']) && isset($data_arr[$i]['RAIN']) && isset($data_arr[$i]['FDI']) && isset($data_arr[$i]['DT']) && isset($data_arr[$i]['LAT']) && isset($data_arr[$i]['LON']) && isset($data_arr[$i]['WD']) && isset($data_arr[$i]['P1']) && isset($data_arr[$i]['AVGCi']) && isset($data_arr[$i]['DT']) && isset($data_arr[$i]['DT']))) {
          // Process error here if not set
        }
        else {
          // If all is well, perform the query
          $id[$key][$i] = $arr['device']['sn'];
          $ts[$key][$i] = $data_arr[$i]['$ts'];
          $RH[$key][$i] = $data_arr[$i]['RH'];
          $AT[$key][$i] = $data_arr[$i]['AT'];
          $MINVi[$key][$i] = $data_arr[$i]['MINVi'];
          $PTi[$key][$i] = $data_arr[$i]['PTi'];
          $SDB[$key][$i] = $data_arr[$i]['SDB'];
          $LWS[$key][$i] = $data_arr[$i]['LWS'];
          $WSAV[$key][$i] = $data_arr[$i]['WSAV'];
          $WSMX[$key][$i] = $data_arr[$i]['WSMX'];
          $WSMN[$key][$i] = $data_arr[$i]['WSMN'];
          $PR_TOT[$key][$i] = $data_arr[$i]['PR_TOT'];
          $RAIN[$key][$i] = $data_arr[$i]['RAIN'];
          $FDI[$key][$i] = $data_arr[$i]['FDI'];
          $DT[$key][$i] = $data_arr[$i]['DT'];
          $LAT[$key][$i] = $data_arr[$i]['LAT'];
          $LON[$key][$i] = $data_arr[$i]['LON'];
          $WD[$key][$i] = $data_arr[$i]['WD'];
          $P1[$key][$i] = $data_arr[$i]['P1'];
          $AVGCi[$key][$i] = $data_arr[$i]['AVGCi'];

          $sql[$key][$i] = "INSERT INTO test(sn, date, RH, AT, MINVi, PTi, SDB, LWS, WSAV, WSMX, WSMN, PR_TOT, RAIN, FDI, DT, LAT, LON, WD, P1, AVGCi)
          VALUES('{$id[$key][$i]}', '{$ts[$key][$i]}', '{$RH[$key][$i]}','{$AT[$key][$i]}', '{$MINVi[$key][$i]}', '{$PTi[$key][$i]}', '{$SDB[$key][$i]}', '{$LWS[$key][$i]}', '{$WSAV[$key][$i]}', '{$WSMX[$key][$i]}', '{$WSMN[$key][$i]}', '{$PR_TOT[$key][$i]}', '{$RAIN[$key][$i]}', '{$FDI[$key][$i]}', '{$DT[$key][$i]}', '{$LAT[$key][$i]}', '{$LON[$key][$i]}', '{$WD[$key][$i]}', '{$P1[$key][$i]}', '{$AVGCi[$key][$i]}')";

          //insert into mysql table
          $query[$key][$i] = mysqli_query($myConnection, $sql[$key][$i]) or die(mysqli_error($myConnection));
        }
      }
    }
  }
}
?>

考慮根據錯誤輸出有條件地構建動態SQL調用。 數組鍵在INSERT子句中創建列,數組值在VALUES子句VALUES引號引起來。 下面回顯sql語句只是為了演示。

對於JSON的任何更改,這都應該起作用,而無需添加其他新鍵。 另外,由於您在date列中傳遞了第二個$ ts值,所以使用array_splice刪除它。

$jsondata = file_get_contents('Input.json');

$data = json_decode($jsondata, true);

$id = $data['device']['sn'];

foreach ($data['data'] as $k=>$v){
    if (array_key_exists("\$msg",$v) & !empty($v)){
       $sql = "INSERT INTO error_log (sn, msg)" 
              ." VALUES('$id', '". $v["\$msg"] ."')";
       echo $sql."\n";
       // INSERT INTO error_log (sn, msg) VALUES('5165654', 'SD_FAIL;1')
       // INSERT INTO error_log (sn, msg) VALUES('5165654', 'WDT;WV01')
       // INSERT INTO error_log (sn, msg) VALUES('5165654', 'WDT;SDI12')
       // INSERT INTO error_log (sn, msg) VALUES('5165654', 'WDT;LWS')

       $query = mysqli_query(...);
    } 
    if (!array_key_exists("\$msg",$v) & !empty($v)) {
       $keysArray = array_keys($v);
       $keysArray = array_splice($keysArray, 1);
       $vVals = array_splice($v, 1);

       $sql = "INSERT INTO test(sn, date, ". implode(", ", $keysArray) .")\n" 
              ." VALUES('$id', '". $v['$ts'] ."',". implode("', '", $vVals) .")";
       echo $sql."\n";

       // INSERT INTO test(sn, date, RH, AT, MINVi, PTi, LWS, WSAV, WSMX, WSMN,
       // PR_TOT, RAIN, FDI, DT, WD, P1, AVGCi)
       // VALUES('5165654', '170801170000',67.15', '12.87', '3.81', '23.4', '0*T',
       //  '0', '0', '0', '156', '0', '0.239', '2.881', '0*T', '0*T', '175)

       $query=mysqli_query(...)
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM