swift 4 Codable - 如果有字符串或字典如何解码?

nas*_*sia 2 swift codable

我有这样的结构:

struct OrderLine: Codable{
    let absUrl: String?
    let restApiUrl : String?
    let description : String?
    let quantity : Int?
    let subscription: Subs?
    let total: Double?
 }

struct Subs: Codable{
    let quantity: Int?
    let name: String?
}
Run Code Online (Sandbox Code Playgroud)

有些OrderLine在服务器响应中

"subscription": {
   "quantity": 6,
   "name": "3 Months"
},
Run Code Online (Sandbox Code Playgroud)

但有时它有String类型:

"subscription": "",
Run Code Online (Sandbox Code Playgroud)

没有subscription一切正常,但我有一个错误

CodingKeys(stringValue: "subscription", intValue: nil)], 
   debugDescription: "Expected to decode Dictionary<String, Any> 
   but found a string/data instead.", underlyingError: nil)
Run Code Online (Sandbox Code Playgroud)

所以我的问题是 - 如何解码 or to String?with value""或 toSubs?而不出现任何错误?ps 如果我只解码它String?,则会出现错误debugDescription: "Expected to decode String but found a dictionary instead.", underlyingError: nil)

Dáv*_*tor 5

您只需要自己实现init(from:)并尝试将键的值解码subscriptionDictionary表示SubsString

struct OrderLine: Codable {
    let absUrl: String?
    let restApiUrl : String?
    let description : String?
    let quantity : Int?
    let subscription: Subs?
    let total: Double?

    private enum CodingKeys: String, CodingKey {
        case absUrl, restApiUrl, description, quantity, subscription, total
    }

    init(from decoder:Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        self.absUrl = try container.decodeIfPresent(String.self, forKey: .absUrl)
        self.restApiUrl = try container.decodeIfPresent(String.self, forKey: .restApiUrl)
        self.description = try container.decodeIfPresent(String.self, forKey: .description)
        self.quantity = try container.decodeIfPresent(Int.self, forKey: .quantity)
        self.total = try container.decodeIfPresent(Double.self, forKey: .total)
        if (try? container.decodeIfPresent(String.self, forKey: .subscription)) == nil {
            self.subscription = try container.decodeIfPresent(Subs.self, forKey: .subscription)
        } else {
            self.subscription = nil
        }
    }
}
Run Code Online (Sandbox Code Playgroud)