Я пытаюсь получить доступ к первому результату этого запроса: 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'. Я неправильно разбираю это?
В опубликованный мной принятый ответ были внесены некоторые изменения. Вы должны посмотреть.
Как видите, есть ключ 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)
}
Примечание: После принятия ответа были внесены некоторые изменения.
Использование
Codable
- это рекомендуемый способ обработки парсинга JSON. Кроме того, поскольку API предоставляет вам значениеposition
, это должно означать, что вы не получаете их в виде отсортированного списка. Вы должны вручную найти пользователя nth. Если нужно, добавляю ответ с реализациейCodable
.