URLSession 成功,但 returns 空 JSON 数据编辑 JSON 解析问题
URLSession successful, but returns empty JSON data EDIT JSON parsing issue
我正在为 iOS 开发一个应用程序,我正在使用 Swift 4 来开发它。该应用程序将使用 REST 调用来填充选择器和表格。下面的代码已用于成功处理呼叫,但是现在,我没有收到任何数据。 REST 已经通过邮递员进行了测试,这给了我预期的结果。
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]()
}
JSON 来自 POSTMAN 的数据
{
"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 被解析。任何人都可以阐明这一点吗?为什么这个简单的改变会奏效?再次感谢。
我使用以下游乐场来说明您的(小)故障:
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
以及第一个版本的 PartType
和 Availability
。这解析完美,所以我认为一切都很好。
然而,您的第一个版本 AccessorySearch
(为了便于比较,我将其设为 AccessorySearch0
)是另一种动物。它不仅定义一个class,它还初始化它。因为它使用 let
来定义它的属性,所以这个第一个赋值不能再改变,你将从 JSONDecoder
得到的将是一个空数组的对象。
正如我所说,这只是一个小故障。
请您隔离问题。首先尝试解析响应..
使用调试器数据可能会指示零字节,请勿以此作为参考。只需解析 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 的实例,您应该会看到响应的内容。
我正在为 iOS 开发一个应用程序,我正在使用 Swift 4 来开发它。该应用程序将使用 REST 调用来填充选择器和表格。下面的代码已用于成功处理呼叫,但是现在,我没有收到任何数据。 REST 已经通过邮递员进行了测试,这给了我预期的结果。
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]()
}
JSON 来自 POSTMAN 的数据
{
"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 被解析。任何人都可以阐明这一点吗?为什么这个简单的改变会奏效?再次感谢。
我使用以下游乐场来说明您的(小)故障:
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
以及第一个版本的 PartType
和 Availability
。这解析完美,所以我认为一切都很好。
然而,您的第一个版本 AccessorySearch
(为了便于比较,我将其设为 AccessorySearch0
)是另一种动物。它不仅定义一个class,它还初始化它。因为它使用 let
来定义它的属性,所以这个第一个赋值不能再改变,你将从 JSONDecoder
得到的将是一个空数组的对象。
正如我所说,这只是一个小故障。
请您隔离问题。首先尝试解析响应.. 使用调试器数据可能会指示零字节,请勿以此作为参考。只需解析 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 的实例,您应该会看到响应的内容。