JSON对象解析但忽略集合中的第一项

时间:2018-12-17 22:32:28

标签: json swift

我正在尝试访问此查询的第一个结果: https://www.instagram.com/web/search/topsearch/?query=_myUsername

我可以像这样获取JSON对象:

var request = URLRequest(url: URL(string: api)!)
request.httpMethod = "GET"
let task = URLSession.shared.dataTask(with: request) { data, response, error in
    guard let data = data, error == nil else { // check for fundamental networking error
        print("error=\(error ?? "" as! Error)")
        return
    }

    do {
        let jsonResponse = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]
        completionHandler(jsonResponse,nil)

    } catch let parsingError {
        print("Error", parsingError)
    }

    if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {  // check for http errors
        print("statusCode should be 200, but is \(httpStatus.statusCode)")
        print("response = \(String(describing: response))")
    }

}
task.resume()

结果是一个JSON对象,该对象忽略了“用户”中的第一个用户。例如,如果我解析JSON对象以获取像这样的结果中第一个用户的用户名...

if let users = jsonResponse!["users"] as? [Any] {
    if let first = users.first as? [String: Any] {
        if let user = first["user"] as? [String: Any] {
            self.igUser = user["username"] as! String

...它返回“位置= 1”用户的用户名,而我实际上希望“位置= 0”用户。我在解析这个错误吗?

1 个答案:

答案 0 :(得分:1)

如您所见,有一个键position,您应该假定该列表未排序。您必须找到列表的 nth 元素。

最小的Codable实现是:

struct TopSearchAPIResponse: Codable {
    let users: [User]
    //let places, hashtags: [Type] // As these two are empty arrays you don't know 
                                   // their type in advance. So you can omit them 
                                   // for now. When you know their type you can 
                                   // use them by providing actual type.
    let hasMore: Bool
    let rankToken: String
    let clearClientCache: Bool
    let status: String

    struct User: Codable {
        let position: Int
        let user: UserInfo

        struct UserInfo: Codable {
            let pk: String
            let username: String
            let fullName: String
            let isPrivate: Bool
            let profilePicURL: URL
            let profilePicID: String?
            let isVerified: Bool
            let hasAnonymousProfilePicture: Bool
            let followerCount: Int
            let reelAutoArchive: ReelAutoArchive
            let byline: String
            let mutualFollowersCount: Int
            let unseenCount: Int

            private enum CodingKeys: String, CodingKey {
            /* This enum is necessary as we want profile_pic_url & profile_pic_id  
            to be decoded as profilePicURL & profilePicID respectively (instead of 
            profilePicUrl & profilePicId) so that we follow Swift conventions */

                case pk
                case username
                case fullName
                case isPrivate
                case profilePicURL = "profilePicUrl"
                case profilePicID = "profilePicId"
                case isVerified
                case hasAnonymousProfilePicture
                case followerCount
                case reelAutoArchive
                case byline
                case mutualFollowersCount
                case unseenCount
            }

            enum ReelAutoArchive: String, Codable {
                case off
                case on
                case unset
            }
        }
    }
}

您将其用作:

do {
    let jsonDecoder = JSONDecoder()
    jsonDecoder.keyDecodingStrategy = .convertFromSnakeCase
    let response = try jsonDecoder.decode(TopSearchAPIResponse.self, from: data)
    if let firstUser = response.users.first(where: { $0.position == 0 }) {
        print(firstUser.user.username) // prints "myusernameisverygay"
    }
} catch {
    print(error)
}

注意::接受答案后已进行了一些修改。