解析JSON数据并插入MySQL

时间:2017-09-07 02:16:25

标签: php mysql json

所以基本上我想用PHP解析一个JSON文件并将数据插入到特定的表/列中。目前我有一个工作脚本,但要求我在很大程度上修改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表

Table Screenshot

JSON数组var_dump - JSON var dump

任何帮助都会很棒

(在我得到一般要点后,我想要加入PDO)

4 个答案:

答案 0 :(得分:2)

  1. 不要盲目地将json转换为关联数组。它会产生更多问题。
  2. 用于访问包含特殊字符或保留的属性 单词使用占位符,如$data->{'$ts'}
  3. 如果需要,循环遍历数组和对象。
  4. 向表中添加自动增量id列有助于存储数据 对于一个设备。
  5. 最好将time添加到error_log表格
  6. 测试了原始问题的短版本,它可以正常工作。

    <?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);
    
    ?>
    

答案 1 :(得分:0)

看起来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作为插件。

它应该可以正常工作......

希望有所帮助。

答案 2 :(得分:0)

也许这样的事情可以让你走上正轨...我注意到的一件事是在给定的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));
        }
      }
    }
  }
}
?>

答案 3 :(得分:0)

考虑根据错误输出有条件地构建动态SQL调用。数组键在INSERT子句中创建列,数组值包含在VALUES子句中。下面回应sql语句只是为了演示。

这应该适用于任何更改为JSON就足够了,不会添加其他新密钥。此外,array_splice用于在 date 列中传递 $ ts 值以来第二次删除 $ ts 值。

$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(...)
    }
}