使用泛型和Decodable

时间:2019-01-30 23:09:06

标签: json swift generics codable swift4.2

我正在尝试制作一个应用程序,以学习如何在Swift中使用泛型。所以我决定使用Studio Ghibli's API

为此,我执行以下操作:

  1. 创建对API的请求
  2. 获取回复
  3. 解析JSON

就像在其API中一样,所有信息都带有等于baseURL的{​​{1}},所有端点都是https://ghibliapi.herokuapp.com,并返回我们想要的任何信息的数组。因此,对于这种特殊情况,我尝试使用baseURL/foo/films

所以,在我看来,最好有一个通用的解码函数来执行此操作,并返回我们要解码的对应类的数组。

/people

我称之为:

private func decode<T: Decodable>(json: Data, as clazz: T) {
    do {
        let decoder = JSONDecoder()
        let films = try decoder.decode([T].self, from: json)
    } catch {
        print("An error occurred while parsing JSON")
    }
}

我的self.decode(json: safeData, as: Films.self) //Error thrown here 类如下:

Films

但是我不断收到错误消息:

import Foundation
import CoreData

@objc(Films)
public class Films: NSManagedObject, Decodable {
    enum CodingKeys: String, CodingKey {
        case id
        case title
        case film_description = "description"
        case director
        case producer
        case release_date
        case rt_score
    }

    required public init(from decoder: Decoder) throws {
        guard let context = CodingUserInfoKey(rawValue: "context"),
            let managedObjectContext = decoder.userInfo[context] as? NSManagedObjectContext,
            let entity = NSEntityDescription.entity(forEntityName: "Films", in: managedObjectContext) else {
                fatalError("Failed to decode Films!")
        }
        super.init(entity: entity, insertInto: nil)

        let container = try decoder.container(keyedBy: CodingKeys.self)
        do {
            id = try container.decodeIfPresent(String.self, forKey: .id)
            title = try container.decodeIfPresent(String.self, forKey: .title)
            film_description = try container.decodeIfPresent(String.self, forKey: .film_description)
            director = try container.decodeIfPresent(String.self, forKey: .director)
            producer = try container.decodeIfPresent(String.self, forKey: .producer)
            release_date = try container.decodeIfPresent(String.self, forKey: .release_date)
            rt_score = try container.decodeIfPresent(String.self, forKey: .rt_score)
        } catch let error {
            print(error)
            throw error
        }
    }
}

我已经在Swift论坛中阅读了以下主题:

有些人说这些解决方案对他们有用,但这与我的概念相同,我仍然不知道如何解决。

正确的方法是什么?

1 个答案:

答案 0 :(得分:1)

解决方案非常简单:

此功能:

private func decode<T: Decodable>(json: Data, as clazz: T) {

蜜饯:

private func decode<T: Decodable>(json: Data, as clazz: T.Type) {

就是这样!这就是所有要做的事情