【问题标题】:URLSession successful, but returns empty JSON data EDIT JSON parsing issueURLSession 成功,但返回空 JSON 数据 编辑 JSON 解析问题
【发布时间】:2018-05-01 16:23:34
【问题描述】:

我正在开发一个适用于 iOS 的应用程序,我正在使用 Swift 4 来开发它。该应用程序将利用 REST 调用来填充选择器和表格。下面的代码已用于成功处理呼叫,但是现在,我没有收到任何数据。 REST 已经过 postman 测试,结果符合预期。

typealias JSONCompletionHandler = (Data?, Int?, Error?) -> void

static function getData(completionHandler: @escaping JSONCompletionHandler){
    let url = URL(string: "http://apiurl.com")
    let task = URLSession.shared.dataTask(with: url!) { data, response, error in
        let htttResponse = response as? HTTPURLResponse

        completeionHandler(data, httResponse?,statuscode, error)
    }
    task.resume()
}

编辑

以下是 HTTPURLResponse 的打印输出

Headers {
"Cache-Control" =     (
    "no-store, no-cache, must-revalidate, post-check=0, pre-check=0"
);
Connection =     (
    "Keep-Alive"
);
"Content-Type" =     (
    "application/json; charset=utf-8"
);
Date =     (
    "Tue, 01 May 2018 15:44:27 GMT"
);
Expires =     (
    "Thu, 19 Nov 1981 08:52:00 GMT"
);
"Keep-Alive" =     (
    "timeout=5, max=100"
);
Pragma =     (
    "no-cache"
);
Server =     (
    "Apache/2.2.29 (Win32) mod_ssl/2.2.29 OpenSSL/0.9.8zf"
);
"Set-Cookie" =     (
    "ZDEDebuggerPresent=php,phtml,php3; path=/"
);
"Transfer-Encoding" =     (
    Identity
);
"X-Powered-By" =     (
    "ZendServer 8.0.2"
);
} }

apache 连接日志

应用

  • [02/May/2018:09:51:04 +0100] "GET /public/rest/catalogue-standard-fit/HTTP/1.1" 200 15669
  • [02/May/2018:09:51:04 +0100] “GET /public/rest/catalogue-multi-fit/HTTP/1.1”200 14302
  • [02/May/2018:09:51:04 +0100] "GET /public/rest/catalogue-accessory/HTTP/1.1" 200 216

邮递员

10.2.13.221 - - [02/May/2018:09:52:55 +0100] "GET /public/rest/catalogue-accessory/HTTP/1.1" 200 216

编辑

正在返回数据,问题在于用于解析 JSON 数据的方法。

我正在使用 swift 4 中可用的 Codable 方法,使用的结构以及 JSON 数据输出的方式如下(来自邮递员)

//Structures for JSON
struct PartType: Codable {
    let id: String
    let name: String
}

struct Availability: Codable {
    let id: String
    let status: String
}

struct AccessorySearch: Codable {
    let part_type = [PartType]()
    let availability = [Availability]()

}

来自 POSTMAN 的 JSON 数据

{
"part_type": [
    {
        "id": "1",
        "name": "Type 1"
    },
    {
        "id": "2",
        "name": "Type 2"
    },
    {
        "id": "3",
        "name": "Type 3"
    }
],
"availability": [
    {
        "id": "1",
        "status": "In Stock"
    },
    {
        "id": "2",
        "status": "In Development"
    },
    {
        "id": "3",
        "status": "Not in Stock"
    }
]
}

使用的方法

    private func jsonDecodeString(data: Data?) {


    // array of the above structures 
    paryTypeArrayStructure.insert(PartType(id: "0", name: "Select Option"), at: 0)
    availabilityArrayStructure.insert(Availability(id: "0", status: "Select Option"), at: 0)

    let decoder = JSONDecoder()
    do {

        let decodeAccessories = try decoder.decode(AccessorySearch.self, from: data!)
        print("PART TYPE: ",decodeAccessories.part_type)
        print("AVAILABILITY: ",decodeAccessories.availability)

        let json = try JSONSerialization.jsonObject(with: data!, options: []) as! [String: AnyObject]

        print(json)

        for item in decodeAccessories.availability {
            print(item)
            availabilityArrayStructure.append(item)
        }

        for item in decodeAccessories.part_type {
            paryTypeArrayStructure.append(item)
        }

        //print(availabilityArrayStructure)
    } catch let jsonErr {
        print ("Failed to decode: ", jsonErr)
        displayErrorMessage(message: "[RCCA003 JSONException occurred when reading the response from server]")
    }

}

我尝试了 JSONSerilization 并能够解析数据。所以现在我的问题是,为什么我最初的尝试解析失败了?对于任何混淆,我深表歉意,你们都非常有帮助,所以谢谢。

编辑 - 找到解决方案...但为什么它起作用了?

首先,我要感谢所有评论和提供研究领域的人。原来是 JSON 解析以及我如何设置结构的问题。

//Structures for JSON
struct PartType: Codable {
    let id: String?
    let name: String?
}

struct Availability: Codable {
    let id: String?
    let status: String?
}

struct AccessorySearch: Codable {

    let part_type:  [PartType]
    let availability: [Availability]
}

将解析 part_type 数组和可用性数组的结构将其变量设置为可选。这允许解析 JSON。任何人都可以对此有所了解吗?为什么这个简单的改变会奏效?再次感谢。

【问题讨论】:

  • 嗯,这是一个非常抽象的问题。您能否发布一些您的JSONCompletionHandler 或者更好的是errordata(以String 形式)和response 的打印输出?
  • 这段代码甚至无法编译。
  • 上面的代码存在一些问题,但是当您使用 HTTP 时,您是否在 App Transport Security Settings 下的 info.plist 中将 Allow Arbitrary Loads 设置为 YES? stackoverflow.com/questions/31254725/…
  • 感谢您的快速回复。 @Patru 问题是任务以状态 200 完成。但是返回的 JSON 数据是空的,当我在 Postman 中进行相同的调用时,我得到了我想要的数据。很遗憾,我无法给您提供您自己测试 API 的 URL,因此我正在检查上述代码中是否有任何错误。
  • @rbaldwin 这个错误没有出现,我遇到的问题是返回的 JSON 数据为空

标签: ios json swift rest nsurlsession


【解决方案1】:

我使用以下 Playground 来说明您的(小)故障:

import Cocoa

let jsonData = """
{
"part_type": [
    {
        "id": "1",
        "name": "Type 1"
    },
    {
        "id": "2",
        "name": "Type 2"
    },
    {
        "id": "3",
        "name": "Type 3"
    }
],
"availability": [
    {
        "id": "1",
        "status": "In Stock"
    },
    {
        "id": "2",
        "status": "In Development"
    },
    {
        "id": "3",
        "status": "Not in Stock"
    }
]
}
""".data(using: .utf8)!

struct PartType: Codable {
    let id: String
    let name: String
}

struct Availability: Codable {
    let id: String
    let status: String
}

struct AccessorySearch0: Codable {
    let part_type = [PartType]()
    let availability = [Availability]()
}

struct AccessorySearch: Codable {
    let part_type: [PartType]
    let availability: [Availability]
}

do {
    let accessory = try JSONDecoder().decode(AccessorySearch.self, from: jsonData)
    print(accessory)
} catch {
    print(error)
}

我使用了您第二个版本中的 AccessorySearch 以及您第一个版本中的 PartTypeAvailability。这完美解析,所以我认为一切都很好。

但是,您的第一个版本 AccessorySearch(我将其命名为 AccessorySearch0 以便于比较)是不同的动物。它不仅定义一个类,它还初始化它。因为它使用let 来定义它的属性,所以这个第一个赋值不能再改变了,你从JSONDecoder 得到的只是一个空数组的对象。

正如我所说,这只是一个小故障。

【讨论】:

  • 这解释了我遇到的故障。非常感谢,以后我会注意如何定义变量。
  • 在 StackOverflow 上习惯于在解决您的问题时接受答案(它甚至会在第一次为您赢得一些分数 :-)
  • 抱歉
  • 无需抱歉。 Stackoverflow 是一个促进学习的网站。提出问题,变得更好并开始回答一些问题。她周围的每个人都明白,这样做需要时间。
【解决方案2】:

请您隔离您的问题。首先尝试解析响应.. 使用调试器数据可能会指示零字节,请勿将此作为参考。只需解析 try 块内的响应

do {
  //full dictionary response
  let json = 
  try JSONSerialization.jsonObject(with: data!, options: .mutableLeaves) as?Dictionary<String, AnyObject>
  //doe son parse correctly ?
catch {
  print(error.localizedDescription)
}

如果您使用 expectedContentLength 变量检查 URLResponse 的实例,您应该会看到响应的内容。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-27
    • 2018-04-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多