获取JSON值到数组

时间:2018-10-11 05:50:40

标签: ios arrays json swift xcode

我需要从MYSQL获取JSON值并将其显示在表格视图中。我已经完成PHP部分以接收数据,但是我的XCODE错误。我的数据将存储温度,湿度和传感器的数字状态(开/关)。我有以下问题:

  1. 如何获取ON / OFF JSON值并将其存储在Bool数组中?
  2. 如何获取JSON值并将其存储在Float数组中?
  3. 如果JSON值为,如何在XCODE中将值存储为0?

class DataManager {
  var nodenameArray: [String] = []
  var nodeidArray: [String] = []
  var tempArray: [Float] = []
  var humArray: [Float] = []
  var pirArray: [Bool] = []
  var lightArray: [Bool] = []
  var relayArray: [Bool] = []
  var hallArray: [Bool] = []
  var smokeArray: [Bool] = []

  @objc func taskdo() {
    self.nodenameArray = []
    self.nodeidArray = []
    self.tempArray = []
    self.humArray = []
    self.pirArray = []
    self.lightArray = []
    self.relayArray = []
    self.hallArray = []
    self.smokeArray = []

    if userlogin == true {
      let request = NSMutableURLRequest(url: NSURL(string: http://talectric.com/wp-admin/a_p/iot/read_all.php")! as URL)
        request.httpMethod = "POST"
        let postString = "username=\(username)&password=\(password)&authen=wdwfesf9329140dsvfxkciospdkm"

        request.httpBody = postString.data(using: String.Encoding.utf8)

        let task = URLSession.shared.dataTask(with: request as URLRequest) {
            data, response, error in
            if error != nil {
                print("error=\(error!)")
                return
            } else {
                do {
                    if let respondString = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? NSDictionary {
                        print(respondString)
                        if let nodedata = respondString.value(forKey: "nodedata") as? NSArray {
                            for node in nodedata{
                                if let nodeDict = node as? NSDictionary {
                                    if let nodeid = nodeDict.value(forKey: "node_id") {
                                        self.nodeidArray.insert(nodeid as! String, at: 0)
                                    }
                                    if let nodeid = nodeDict.value(forKey: "node_name") {
                                        self.nodenameArray.insert(nodeid as! String, at: 0)
                                    }
                                    if let nodeid = nodeDict.value(forKey: "temp") {
                                        self.tempArray.insert(Float(nodeid as! String)!, at: 0)
                                    }
                                    if let nodeid = nodeDict.value(forKey: "hum") {
                                       print(nodeid)
                                        self.humArray.insert(Float(Int(nodeid as! String)!), at: 0)                
                                    }
                                }
                            }
                        }
                    }
                    print(self.nodenameArray)
                    print(self.nodeidArray)
                    print(self.tempArray)
                    print(self.humArray)
                    NotificationCenter.default.post(name: NSNotification.Name(rawValue: "load"), object: nil)
                }
                catch let error as NSError {
                    print(error.debugDescription)
                }
            }
        }
        task.resume()
    }
  }
}

下面是响应:

{
    nodedata =     (
            {

        "hall_status" = "<null>";

        hum = 111;

        "light_status" = "<null>";

        "node_id" = y2cfwecrw3hqznuxmfvf;

        "node_name" = SVIN03;

        "pir_status" = OFF;
        "relay_status" = "<null>";
        "smoke_status" = "<null>";
        temp = 2132;
    },
            {
        "node_name" = SVIN04;
        nodeid = aj2w1aljw8nd65ax79dm;
    },
            {
        "hall_status" = "<null>";
        hum = 100;
        "light_status" = "<null>";
        "node_id" = mwmfl2og2l8888fjpj2d;
        "node_name" = SVIN05;
        "pir_status" = ON;
        "relay_status" = "<null>";
        "smoke_status" = "<null>";
        temp = 45;
    }
);
numberofnodeid = 3;
}

111 100

  

无法将类型'__NSCFNumber'(0x10db6f878)的值强制转换为'NSString'(0x10ca71568)。   2018-10-11 08:11:05.352491 + 0700 IOT 2 [1506:101847]无法将类型'__NSCFNumber'(0x10db6f878)的值强制转换为'NSString'(0x10ca71568)。

此行有错误:

self.humArray.insert(Float(Int(nodeid as! String)!), at: 0)

3 个答案:

答案 0 :(得分:0)

首先,您必须查看json_decode才能从php中的json读取数据

示例:

`$json = '{"foo-bar": 12345}';
$obj = json_decode($json);
print $obj->{'foo-bar'}; // this will print 12345`

如何获取ON / OFF JSON值并将其存储在Bool数组中? 基本上,您必须向onOff变量添加一个新值,例如

$onOff=array();
$val;
$obj = json_decode($json);
if (is_null($obj->{'name_of_the_alert'})) {
   $val = 0
} else {
   $val = $obj->{'name_of_the_alert'};
}
array_push($onOff,$obj->{'name_of_the_alert'});    

如何获取JSON值并将其存储在Float数组中? 基本上是同一件事,我已经有一段时间没有使用PHP了,只是声明您需要的值类型的数组。

如果JSON值为,我如何在XCODE中将值存储为0?  我猜你的意思是如果它为null,在这种情况下,你必须这样做

$onOff=array();
$val;
$obj = json_decode($json);
if (is_null($obj->{'name_of_the_alert'})) {
   $val = 0
} else {
   $val = $obj->{'name_of_the_alert'};
}
array_push($onOff,$obj->{'name_of_the_alert'});

考虑到我在这里可能会犯一些错误,因为我不熟悉较新的PHP版本。

祝你好运

答案 1 :(得分:0)

从您的问题来看,很清楚temphum是数字类型(双精度整数)。因此,使用NSNumber而不是NSString作为

self.humArray.insert(Float(Int(nodeid as! NSNumber)!), at: 0) 

作为更快捷的方法,您可以将代码更新为:

if let nodeDict = node as? [String: Any] {
    if let nodeid = nodeDict["node_id"] as? String {
        self.nodeidArray.insert(nodeid, at: 0)
    }
    if let nodename = nodeDict["node_name"] as? String {
        self.nodenameArray.insert(nodename, at: 0)
    }
    if let temp = nodeDict["temp"] as? Int {
        self.tempArray.insert(Float(temp), at: 0)
    }
    if let hum = nodeDict["hum"] as? Int {
        self.humArray.insert(Float(hum), at: 0)                
    }
}

答案 2 :(得分:0)

您的代码有很多问题:

首先,避免在等效的Swift3 +中使用NSStuff。

let request = NSMutableURLRequest(url: NSURL(string: http://talectric.com/wp-admin/a_p/iot/read_all.php")! as URL)
...
let task = URLSession.shared.dataTask(with: request as URLRequest) {

=>

let request = URLRequest(url: URL(string: http://talectric.com/wp-admin/a_p/iot/read_all.php")!)
...
let task = URLSession.shared.dataTask(with: request) {

瞧,您已经避免了所有as URLas URLRequest

避免强行展开:避免使用!。 因为如果它为nil或使用as!强制转换失败(然后为nil),则会导致崩溃。 使用if letguard letRead this about Optional

作为示例,我会写:

guard let url = URL(string:http...) else {
    print("invalid URL")
    return
}
let request = URLRequest(url: url)

解析部分:

if let respondString = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? NSDictionary {

摆脱NSDictionary,改用[String: Any],然后摆脱.allowFragments,这很少有用(仅在某些情况下才有意义) data!,并且不要命名变量respondString  因为这显然不是String,而且显然具有误导性。

=>

guard let data = data else { return }
if let responseDict = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] {

现在:

if let nodedata = respondString.value(forKey: "nodedata") as? NSArray {
    for node in nodedata{
        if let nodeDict = node as? NSDictionary {
            if let nodeid = nodeDict.value(forKey: "node_id") {
                self.nodeidArray.insert(nodeid as! String, at: 0)
            }
            if let nodeid = nodeDict.value(forKey: "node_name") {
                self.nodenameArray.insert(nodeid as! String, at: 0)
            }
            if let nodeid = nodeDict.value(forKey: "temp") {
                self.tempArray.insert(Float(nodeid as! String)!, at: 0)
            }
            if let nodeid = nodeDict.value(forKey: "hum") {
               print(nodeid)
                self.humArray.insert(Float(Int(nodeid as! String)!), at: 0)                
            }
        }
    }
}

否,否NSArray,否NSDictionary,请避免使用value(forKey:),因为它会像您在NSDictionary上所做的那样执行object(forKey:),或者只需下标(使用["someKey"]),但是在Array上,您会遇到一个问题,我想这是意外的结果。 不要命名您的所有变量nodeid,在病房之后更难以调试,如果只是在此值之后进行强制解包,也不要进行软解包(if let)。

if let nodedata = responseDict["nodedata"] as? [[String: Any]] {
    for aNode in nodedata {
        if let id = aNode["node_id"] as? String {
            self.nodeidArray.insert(nodeId, at: 0)
        }
        if let name = aNode["node_name"] as? String {
            self.nodenameArray.insert(name, at: 0)
        }
        if let temp = aNode["temp"] as? String, let tempFloat = Float(temp) {
            self.tempArray.insert(tempFloat, at: 0)
        }
        if let hum = aNode["hum"] as? String, let humFloat = Float(hum) {
            self.humArray.insert(humFloat, at: 0)                
        }
    }
}

那更具可读性。

现在,使用insert(_:at:)可能会更容易,而不是使用nodedata.inverted()

现在,让我们谈谈架构: 如果您在一次迭代中不通过if let hum = aNode["hum"] as? String, let humFloat = Float(hum) {(假设第二次恰好是您所提供的样本中的情况,则没有temp),那么您的情况将如何?其他? 这将发生什么: self.nodeidArray[3]self.humArray[3]将不正确,它们将被取消同步,对吗? 因为self.nodeidArray[2]应该和self.humArray[1]一起使用。

这些值是要同步的,因此请使用自定义的Struct / Class: 毕竟,Swift是一种OOP(面向对象编程)语言,因此请使用对象。

struct Node {
    let id: String?
    let name: String?
    let humidity: Float?
    let temperature: Float?
}

所以没有:

var nodenameArray: [String] = []
var nodeidArray: [String] = []
var tempArray: [Float] = []
var humArray: [Float] = []

只需:

var nodes: [Node] = []

在解析过程中,执行

let node = Node.init(withDict: aNode)
nodes.append(node) //or insert it at 0

您可以在Node中构造自己的方法init,例如:

func init(withDict dict: [String: Any]) {
    if let id = dict["node_id"] as? String {
        self.id = id
    }
    etc.
}

简化此Node类。但是使用Codable(在Swift 4中可用)可以避免使用JSONSerialization并手动初始化所​​有值。

旁注:

此代码未经测试,可能存在一些故障,错别字等。让我们集中精力进行解释。

最后与该错误有关:

  

无法将类型'__NSCFNumber'(0x10db6f878)的值强制转换为   'NSString'(0x10ca71568)。 2018-10-11 08:11:05.352491 + 0700 IOT   2 [1506:101847]无法转换类型'__NSCFNumber'的值   (0x10db6f878)到'NSString'(0x10ca71568)。

     

此行有错误:

     

self.humArray.insert(Float(Int(nodeid as! String)!), at: 0)

该错误意味着您有时尝试在a as上级联(使用(NS)String),但实际上是NSNumber(在Swift中,它很容易转换为{ {1}} / Int等),因此失败。 因此失败的部分:Float,因为nodeid as! String不是nodeid