对于从可解码兼容类派生的类(JSONDecoder 用于解码),Swift Decodable 失败

编程入门 行业动态 更新时间:2024-10-22 18:47:56
本文介绍了对于从可解码兼容类派生的类(JSONDecoder 用于解码),Swift Decodable 失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 public struct CodeAndDetails: Codable { public let html: String public var code: String private enum CodingKeys: String, CodingKey { case html = "DETAILS", code = "CODE" } public func getMessage(font: UIFont) -> NSAttributedString? { let res = NSAttributedString(html: html, font: font) return res } } public class BaseResponse: Decodable { enum CodingKeys: String, CodingKey { case successDetails = "Success" } public let successDetails: [CodeAndDetails] }

这里:

public class CardListResponse: BaseResponse { public var cards: [DebitCard]? public var activeCardId: Int? enum CodingKeys: String, CodingKey { case cards = "row" case activeCardId = "CurrentActiveId" } }

未正确解码.卡和 activeCardId 保持为零.当我将公共类 CardListResponse: BaseResponse 更改为公共类 CardListResponse: 可解码卡片和 activeCardId 解析就好了(但显然我没有从基类中获得有效负载).

Does not decode properly. cards and activeCardId stay nil. When I change public class CardListResponse: BaseResponse to public class CardListResponse: Decodable the cards and activeCardId parse just fine (but obviously I get no payload from base class).

我该如何应对?

如果从这里的示例 json 的问题中不清楚:

In case it's not clear from the question here's sample json:

我的 JSON

{ "row":[ { "PicPath":"MC" }, { "IsDefault":"", "PicPath":"VISA" } ], "CurrentActiveId":17504322, "Success":[ { "DETAILS":"\u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043e \u0443\u0441\u043f\u0435\u0448\u043d\u043e", "CODE":"1" } ] }

public struct DebitCard: Decodable { public let accountContractId: Int? public let last8: String? public let balanceString: String? public let currName: String? public let iCardId: Int? public let isMain: Bool? public let cardNameWithCurrencyCode: String? public let card4: String? public let title: String? public let picPath: String? enum CodingKeys: String, CodingKey { case accountContractId = "AcntContractId" case expire = "Expire" case last8 = "Card8" case balanceString = "Balance" case currName = "CurrName" case iCardId case isMainString = "isMain" case cardNameWithCurrencyCode = "CardName" case card4 = "Card4" case title = "CrdTInfo" case picPath = "PicPath" } public init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) accountContractId = try values.decode(Int.self, forKey: .accountContractId) last8 = try values.decode(String.self, forKey: .last8) balanceString = try values.decode(String.self, forKey: .balanceString) currName = try values.decode(String.self, forKey: .currName) iCardId = try values.decode(Int.self, forKey: .iCardId) let isMainString = try values.decode(String.self, forKey: .isMainString) isMain = isMainString.toBool cardNameWithCurrencyCode = try values.decode(String.self, forKey: .cardNameWithCurrencyCode) card4 = try values.decode(String.self, forKey: .card4) title = try values.decode(String.self, forKey: .title) picPath = try values.decode(String.self, forKey: .picPath) } }

推荐答案

你需要在子类中实现 init(fromdecoder: Decoder) 并调用超类 init 虽然你不需要为超类实现它

You need to implement init(from decoder: Decoder) in the subclass and call the superclass init although you don't need to implement it for the superclass

init for CardListResponse,注意调用 super.init

init for CardListResponse, notice the call to super.init

required public init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) cards = try container.decode([DebitCard].self, forKey: .cards) activeCardId = try container.decode(Int.self, forKey: .activeCardId) try super.init(from: decoder) }

另一种选择是完全跳过继承并使用组合代替.在子类中,您为 CodeAndDetails 数组创建了一个属性,这样您就不再需要特殊的 init 方法.

Another option is to skip inheritance altogether and use composition instead. In the subclass you make a property for the CodeAndDetails array instead, this way you won't need a special init method anymore.

CardListResponse 然后可以更改为下面,并且可以删除超类.从长远来看,我认为这是一个更有吸引力的解决方案.

CardListResponse can then be changed to below and the super class can be removed. In the long run I think this is a more attractive solution.

public class CardListResponse: Decodable { public var cards: [DebitCard]? public var activeCardId: Int? public var details: [CodeAndDetails] private enum CodingKeys: String, CodingKey { case cards = "row" case activeCardId = "CurrentActiveId" case details = "Success" } }

更多推荐

对于从可解码兼容类派生的类(JSONDecoder 用于解码),Swift Decodable 失败

本文发布于:2023-11-26 18:01:36,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1634607.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:JSONDecoder   Swift   Decodable

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!