Объект JSON анализирует, но пропускает первый элемент в наборе

Я пытаюсь получить доступ к первому результату этого запроса: 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

... Он возвращает имя пользователя 'position = 1', в то время как мне действительно нужен пользователь 'position = 0'. Я неправильно разбираю это?

Использование Codable - это рекомендуемый способ обработки парсинга JSON. Кроме того, поскольку API предоставляет вам значение position, это должно означать, что вы не получаете их в виде отсортированного списка. Вы должны вручную найти пользователя nth. Если нужно, добавляю ответ с реализацией Codable.

nayem 18.12.2018 14:44

В опубликованный мной принятый ответ были внесены некоторые изменения. Вы должны посмотреть.

nayem 19.12.2018 17:53
Как сделать HTTP-запрос в Javascript?
Как сделать HTTP-запрос в Javascript?
В JavaScript вы можете сделать HTTP-запрос, используя объект XMLHttpRequest или более новый API fetch. Вот пример для обоих методов:
1
2
78
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 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)
}

Примечание: После принятия ответа были внесены некоторые изменения.

Другие вопросы по теме