【问题标题】:Get JSON value to Array获取 JSON 值到数组
【发布时间】:2018-10-11 05:50:39
【问题描述】:

我需要从 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)

【问题讨论】:

  • Could not cast value of type '__NSCFNumber' (0x10db6f878) to 'NSString' (0x10ca71568). + Line self.humArray.insert(Float(Int(nodeid as! String)!), at: 0) 表明nodeidNSNumber 而不是String,因为nodeDict.value(forKey: "temp") 不是String
  • 一般来说:避免使用强制展开(使用!)。不要使用所有这些数组来获得同步值。取而代之的是使用自定义结构/类,在 Swift 4 中也可以使用 Codable 可能是一个有趣的想法。不要在 Swift3+ 中使用 NSStuff,当 Swift 中有等价物时:NSMutableURLRequest => URLRequest(这也将避免稍后的as URLRequestNSURL => URL...
  • 你得到temphum作为Int所以使用NSNumber而不是NSString作为self.humArray.insert(Float(Int(nodeid as! NSNumber)!), at: 0)以上参数
  • @Larme 你的意思是我不应该使用这段代码,对吧?如果让 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) }

标签: ios arrays json swift xcode


【解决方案1】:

首先你得看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? 我猜你的意思是如果它为空,在这种情况下你必须这样做

$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 版本。

祝你好运

【讨论】:

  • 当我使用 self.humArray.insert(Float(Int(nodeid as!String)!), at: 0) 存储浮点值(字符串从 JSON 接收并转换为浮点数)时,我创建错误无法将“__NSCFNumber”(0x10db6f878)类型的值转换为“NSString”(0x10ca71568)。 2018-10-11 08:11:05.352491+0700 IOT 2[1506:101847] 无法将“__NSCFNumber”(0x10db6f878)类型的值转换为“NSString”(0x10ca71568)。
  • 在这种情况下,我首先将 nodeid 打印为!字符串到屏幕以确保我们得到了什么,也许那个屏幕上还有其他东西,这就是为什么你不能像那样转换它,因为它应该可以工作。也许字符串中有一个 C 或 F,你需要去掉它。
【解决方案2】:

根据您的问题,很明显temphum 是数字类型(Int of Double)。所以使用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)                
    }
}

【讨论】:

    【解决方案3】:

    你的代码有很多问题:

    首先,当有等价物时,避免在 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 我认为您会遇到意外结果的问题。 不要将所有 var 命名为 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] 在一起。

    这些值是用来同步的,所以使用自定义结构/类: 毕竟 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 类简化。但是使用 JSONSerialization 并手动初始化所​​有值可以避免使用 Codable(在 Swift 4 中可用)。

    旁注:

    此代码未经测试,可能存在一些小故障、错字等。让我们专注于解释。

    最后关于错误:

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

    错误在这一行:

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

    该错误意味着在某些时候您尝试对 (NS)String 进行 cas(使用 as),但实际上是 NSNumber(在 Swift 中,它很容易转换为 Int/Float等),所以它失败了。 所以失败的部分:nodeid as! String,因为nodeid不是(NS)String

    【讨论】:

    • 我创建了 struct struct Node: Codable { var id: String?变量名称:字符串? var 湿度:浮动? var 温度:浮动? init(withDict dict: [String: Any]) { if let id = dict["node_id"] as? String { self.id = id } if let name = dict["node_name"] as? String { self.name = name } 如果让湿度 = dict["hum"] as?如果让温度 = dict[“tem”] 为浮点数 { self.湿度 = 湿度 }?浮动 { self.temperature = 温度 } } }
    • 这个结构创建没有错误。解析也遵循您的建议 if let nodedata = responseDict["nodedata"] as? [[String: Any]] { for aNode in nodedata { let node = Node.init(withDict: aNode) self.nodes.append(node) //或者插入到0
    • 但是如何访问 id 元素? print(nodes.id) // 此代码创建错误:“[Node]”类型的值没有成员“id”
    • 类 DataManager { var 节点:[节点] = []。请帮助我访问 Datamanager 类中的节点元素。
    • 那是为了什么UITableViewnodes.id 没有意义,因为nodes 是一个数组,你想要第一个是nodes[0].id,第二个是nodes[1].id,等等,或者更明确地说:let firstNode: Node = nodes[0], let firstNodeId = firstNode.id
    猜你喜欢
    • 2014-11-25
    • 2017-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-08
    • 2013-12-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多