URLSession成功,但返回空JSON数据EDIT JSON解析问题

时间:2018-05-01 16:23:35

标签: ios json swift rest nsurlsession

我正在开发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 / catalog-standard-fit / HTTP / 1.1" 200 15669
  • [02 / May / 2018:09:51:04 +0100]" GET / public / rest / catalog-multi-fit / HTTP / 1.1" 200 14302
  • [02 / May / 2018:09:51:04 +0100]" GET / public / rest / catalog-accessory / HTTP / 1.1" 200 216

邮差

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

修改

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

我使用swift 4中提供的Codable方法,下面使用的结构以及JSON数据输出的方式(来自postman)

//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数组和可用性数组的结构将其变量设置为optional。这允许解析JSON。任何人都可以对此有所了解吗?为什么这个简单的改变有效?再次感谢。

2 个答案:

答案 0 :(得分:0)

我使用下面的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得到的所有对象都是空数组。

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

答案 1 :(得分:0)

请您隔离问题。首先尝试解析响应。 使用调试器数据可能表示零字节,请勿以此为参考。只需解析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的实例,则应该看到响应的内容。