Swift 4 Codable - API иногда предоставляет Int, а иногда String - PullRequest
0 голосов
/ 04 июня 2018

У меня сейчас работает Codables.Но в API есть некоторые строковые записи, которые иногда могут иметь значение Int, равное 0, если они пусты.Я искал здесь и нашел это: Swift 4 Codable - значения Bool или String Но я не могу его запустить

Моя структура

struct check : Codable {
    let test : Int
    let rating : String?  
}

Рейтингв большинстве случаев что-то вроде "1Star".Но если нет рейтинга, я получаю 0 как Int обратно.

Я анализирую данные следующим образом:

enum Result<Value> {
    case success(Value)
    case failure(Error)
}

func checkStar(for userId: Int, completion: ((Result<check>) -> Void)?) {
    var urlComponents = URLComponents()
    urlComponents.scheme = "https"
    urlComponents.host = "xyz.com"
    urlComponents.path = "/api/stars"
    let userIdItem = URLQueryItem(name: "userId", value: "\(userId)")
    urlComponents.queryItems = [userIdItem]
    guard let url = urlComponents.url else { fatalError("Could not create URL from components") }

    var request = URLRequest(url: url)
    request.httpMethod = "GET"


    let config = URLSessionConfiguration.default
    config.httpAdditionalHeaders = [
        "Authorization": "Bearer \(keytoken)"
    ]

    let session = URLSession(configuration: config)
    let task = session.dataTask(with: request) { (responseData, response, responseError) in
        DispatchQueue.main.async {
            if let error = responseError {
                completion?(.failure(error))
            } else if let jsonData = responseData {
                // Now we have jsonData, Data representation of the JSON returned to us
                // from our URLRequest...

                // Create an instance of JSONDecoder to decode the JSON data to our
                // Codable struct
                let decoder = JSONDecoder()

                do {
                    // We would use Post.self for JSON representing a single Post
                    // object, and [Post].self for JSON representing an array of
                    // Post objects
                    let posts = try decoder.decode(check.self, from: jsonData)
                    completion?(.success(posts))
                } catch {
                    completion?(.failure(error))
                }
            } else {
                let error = NSError(domain: "", code: 0, userInfo: [NSLocalizedDescriptionKey : "Data was not retrieved from request"]) as Error
                completion?(.failure(error))
            }
        }
    }

    task.resume()
}

Загрузка:

func loadStars() {
    checkStar(for: 1) { (result) in
        switch result {
        case .success(let goo):
            dump(goo)
        case .failure(let error):
            fatalError(error.localizedDescription)
        }
    }
}

Я надеюсь, что кто-то может помочь мне там, потому что я не совсем уверен, как работает этот анализ и т. Д.

1 Ответ

0 голосов
/ 04 июня 2018

вы можете реализовать свой собственный метод инициализации декодирования, получить каждое свойство класса из контейнера декодирования, во время этого раздела, сделать свою логику, имеющую дело с более «рейтингом», Int или String, подписать все необходимые свойства класса в конце.

Вот простая демонстрация, которую я сделал:

class Demo: Decodable {
    var test = 0
    var rating: String?

    enum CodingKeys: String, CodingKey {
        case test
        case rating
    }

    required init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        let test = try container.decode(Int.self, forKey: .test)
        let ratingString = try? container.decode(String.self, forKey: .rating)
        let ratingInt = try? container.decode(Int.self, forKey: .rating)
        self.rating = ratingString ?? (ratingInt == 0 ? "rating is nil or 0" : "rating is integer but not 0")
        self.test = test
    }
}

let jsonDecoder = JSONDecoder()
let result = try! jsonDecoder.decode(Demo.self, from: YOUR-JSON-DATA)
  • , если значение API рейтинга является обычной строкой, вы получите его, как хотите.
  • , если значение API рейтинга равно0, рейтинг будет равен "рейтинг равен нулю или 0"
  • , если значение API рейтинга равно другим целым числам, рейтинг будет "рейтинг целое, но не 0"

, который вы можете изменитьдекодированный результат «рейтинга», это должно быть легко.

надеюсь, это поможет вам немного помочь.:)

для получения дополнительной информации: Документация Apple по кодированию и декодированию

...