【问题标题】:Cannot parse JSON (SwiftyJson) from Get to my Web API无法将 JSON (SwiftyJson) 从 Get 解析到我的 Web API
【发布时间】:2017-12-11 01:48:10
【问题描述】:

13.12.2017:请跳转到“更新 3”,因为我已经更改了我的功能!!!


从 HTTP Get 到我的 Web API 我得到一个 JSON 响应,我需要在 TableViewController 中逐行显示数据。但是输出是空的,因为我认为我无法正确地从 data_list 中获取stdata。我认为我在类型方面做错了什么?

这是代码的相关部分:

func extract_json(_ data: Data){

    // added for UPDATE 2
    let string = String.init(data: data, encoding: .utf8)
    print(string)

    do {
        let json = try JSONSerialization.jsonObject(with: data, options: [.allowFragments])
        let data_list = json as? [AnyObject]

        for stdata in data_list! {
            if let StMsgID = stdata["MsgID"] as? String {  // for UPDATE 1: set breakpoint to this line
                if let StSerial = stdata["Serial"] as? String{
                    TableData.append(StMsgID + " : " + StSerial)
                }
            }
        }
    } catch let error as NSError {
        print(error)
        return
    }
    DispatchQueue.main.async(execute: {self.do_table_refresh()})
}

func do_table_refresh()
{
    self.tableView.reloadData()
}

override func numberOfSections(in tableView: UITableView) -> Int {
    return 1
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return TableData.count
}


override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)

    cell.textLabel?.text = TableData[indexPath.row]

    return cell
}

当我在调试器中显示时,这是JSON

▿ 1 element
  - 0 : [{"CreatedAt":"01-11-17 10:46","MsgID":"ST88”,”Serial”:”88”},{“CreatedAt":"03-12-17 21:35","MsgID”:”ST99”,”Serial”:”99”}]

这是data_list

▿ Optional<Array<AnyObject>>
  ▿ some : 1 element
    - 0 : [{"CreatedAt":"01-11-17 10:46","MsgID":"ST88”,”Serial”:”88”},{“CreatedAt":"03-12-17 21:35","MsgID”:”ST99”,”Serial”:”99”}]

我希望在 TableViewController 中看到两行:

ST88 : 88
ST99 : 99

我得到的是一张空桌子。

提前谢谢你!!!

更新 1:

当我将断点设置为行时:

if let StMsgID = stdata["MsgID"] as? String...

当我深入到“stdata” -> 0x... -> NSMutableString -> NSString -> NSObject -> isa 时,我可以看到以下值:

[{"CreatedAt":"01-11-17 10:46","MsgID":"ST88”,”Serial”:”88”},{“CreatedAt":"03-12-17 21:35","MsgID”:”ST99”,”Serial”:”99”}]

它是否正确解析,因为我仍然可以看到这两个数据集?在这一点上,我希望只看到 ST88 的第一个数据集。

更新 2:

将以下代码添加到我的函数顶部:

    let string = String.init(data: data, encoding: .utf8)
    print(string)

输出是:

Optional("[\"[{\\\"CreatedAt\\\":\\\"01-11-17 10:46\\\",\\\"MsgID\\\":\\\"ST88\\\”,\\\”Serial\\\”:\\\”88\\\”},{\\\"CreatedAt\\\":\\\"03-12-17 21:35\\\",\\\"MsgID\\\”:\\\”ST99\\\”,\\\”Serial\\\”:\\\”99\\\”}]\"]")

===================================

更新 3:

我已将代码更改为使用 SwiftyJson,但仍然无法正常工作。

这是我现在使用的最新格式,位于我的 Web API 的响应下方:

["{\"inbox\":[{\"CreatedAt\":\"01-11-17 10:46\",\"MsgID\":\"ST88\",\"Serial\":\"88\"},{\"CreatedAt\":\"03-12-17 21:35\",\"MsgID\":\"ST99\",\"Serial\":\"99\"}]}"]

根据 jsonlint.com,这是有效的。

这是我在 Swift 3 中使用 SwiftyJson 的新功能:

// using SwiftyJSON !!!
func extract_json(_ data: Data)
{
    do
    {
        let json = try JSON(data: data)

        for obj in json["inbox"]
        {
            let value = obj["MsgID"].string // error here (not compiling)
            print (value)
            TableData.append(value)
        }
    }
    catch let error as NSError
    {
        print(error)
        return
    }

    DispatchQueue.main.async(execute: {self.do_table_refresh()})
}

我希望看到:

ST88
ST99

它甚至没有编译,我遇到的错误

let value = obj["MsgID"].string

是:

Value of tuple type '(String, JSON)' has no member 'subscript'

【问题讨论】:

  • do_table_refresh 是做什么的?请在您的问题中包括其实施。一些一般性建议:当您嵌套了没有else 分支的if 语句时,您可以将它们合并为一个用逗号分隔条件的单个语句(if let StMsgID = stdata["MsgID"] as? String, let StSerial = stdata["Serial"] as? String {...})。此外,编译器会自动在catch 块中合成一个error 变量,因此您不需要声明一个变量,尤其不需要将其转换为NSError。就做catch {print(error)}
  • 感谢您的建议。我已经添加了要求的部分。任何帮助表示赞赏。
  • 当你调用tableView.reloadData()时你真的检查TableData.count不为0吗?
  • 这不是之前的问题造成的吗?另请参阅更新 1。
  • 您能否将实际数据作为字符串发布。 let string = String.init(data: data, encoding: .utf8) print(string)

标签: json swift swifty-json


【解决方案1】:

let data_list = json as? [AnyObject] 更改为let data_list = json as? [[String: Any]]


更新:

从您的网络服务器返回的 json 在技术上是有效的 json,但这不是您想要的。当前返回的json是一个字符串列表,你要的是一个对象列表。

您需要更新您的网络服务器以删除第一个 " 和最后一个 "

  • ["{\"inb... 必须是 [{\"inb
  • ...99\"}]}"] 必须是 99\"}]}]

我猜所有的\ 只是额外的信息,因为你已经在调试器中打印了它。但是,如果您从网络服务器获取这些 \,那么您也需要删除这些。

【讨论】:

  • 当我使用 json as? [[String: Any]] 时,data_list 为 nil 并且它正在崩溃......当我使用 json as! [[String: Any]] 时,我得到:无法将类型“__NSCFString”(0x1b552d040)的值转换为“NSDictionary” ' (0x1b552db80)。此时调试器中的json为: ▿ 1 element - 0 : [{"CreatedAt":"01-11-17 10:46","MsgID":"ST88","Serial":"88"},{ “CreatedAt”:"03-12-1‌​7 21:35","MsgID":”ST99”,”Serial”:”99”}]
  • json进入iOS应用前是什么样子的?您可以尝试使用 Postman 或类似的东西来获取原始 json 吗? getpostman.com
  • 我现在正在尝试使用 SwiftyJson,我还发布了最新的 json。请参阅更新 3。
  • @Romeosan 真正的问题是从您的后端返回的 json。请参阅我的更新答案。
  • 太好了,这就是问题所在。我的 c# web api 作为字符串返回,在将返回类型更改为 HttpResponseMessage 作为“application/json”后,我去掉了引号。现在我返回对象并从 [[String: Any]] 开始解析它们。非常感谢!
【解决方案2】:

在您的json 中,路由元素是一个数组,其中包含字典数组(数组数组)。因此,如果您需要按照描述提取值,您应该获取根数组的第一个对象,然后对其进行迭代。意思是:

let data_list = json as? [[[String: Any]]]

代替

let data_list = json as? [AnyObject]

在 for 循环内的当前实现中,stdata 是一个数组。

【讨论】:

  • 谢谢,但这也不起作用,data_list 是 nil 所以现在我正在尝试使用 SwiftyJson。请参阅 UPDATE3。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-07
  • 1970-01-01
  • 2022-01-08
  • 1970-01-01
  • 2018-11-10
相关资源
最近更新 更多