我想要一个可以通过普通的可编码协议或字典实例化的Struct(现有代码需要字典实例化(。
我在操场上有这段代码,但我不确定在我的第二次初始化中该做什么,因为它需要一个Dictionary。如何从字典中生成Decoder对象?
import Foundation
public protocol Parsable: Decodable {
init(dict: [String: Any]) throws
}
struct LinkModel: Parsable {
var href: String
var text: String
init(dict: [String: Any]) throws {
href = "/store/options.aspx"
text = "Buy"
}
}
struct ResponseModel: Parsable {
var link: LinkModel?
let showCell: Bool
enum CodingKeys : String, CodingKey {
case link
case showCell = "show"
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let linkResponses = try container.decode([LinkModel].self, forKey: .link)
link = linkResponses.first
showCell = try container.decode(Bool.self, forKey: .showCell)
}
init(dict: [String: Any]) throws {
let jsonData = try JSONSerialization.data(withJSONObject: dict, options: [])
let decoder = ??? // what do I do here?
self.init(from: decoder)
}
}
let jsonText = """
{
"show": true,
"link": [
{
"text": "Buy",
"href": "/store/options.aspx"
}
]
}
"""
// test standard Decodable instantiation
let jsonData = jsonText.data(using: .utf8)!
let model = try! JSONDecoder().decode(ResponseModel.self, from: jsonData)
print(model.link?.href)
// test dictionary instantiation
...
扩展Parsable
协议以自动生成您要查找的初始值设定项。
extension Parsable {
init(dict: [String: Any]) throws {
let jsonData = try JSONSerialization.data(withJSONObject: dict, options: [])
let decoder = JSONDecoder()
self = try decoder.decode(Self.self, from: jsonData)
}
}
你走在了正确的道路上。
import Foundation
public protocol Parsable: Decodable {
init(dict: [String: Any]) throws
}
struct LinkModel: Parsable {
var href: String
var text: String
init(dict: [String: Any]) throws {
href = "/store/options.aspx"
text = "Buy"
}
}
struct ResponseModel: Parsable {
var link: LinkModel?
let showCell: Bool
enum CodingKeys : String, CodingKey {
case link
case showCell = "show"
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let linkResponses = try container.decode([LinkModel].self, forKey: .link)
link = linkResponses.first
showCell = try container.decode(Bool.self, forKey: .showCell)
}
init(dict: [String: Any]) throws {
let jsonData = try JSONSerialization.data(withJSONObject: dict, options: [])
// 1.
let decoder = JSONDecoder()
// 2.
let result = try decoder.decode(ResponseModel.self, from: jsonData)
// 3.
self = result
}
}
let jsonText = """
{
"show": true,
"link": [
{
"text": "Buy",
"href": "/store/options.aspx"
}
]
}
"""
// test standard Decodable instantiation
let jsonData = jsonText.data(using: .utf8)!
let model = try! JSONDecoder().decode(ResponseModel.self, from: jsonData)
print(model.link?.href)
我所做的只是:
- 创建一个JSONdecoder对象
- 使用该JSONdecoder对
ResponseModel
类型的对象进行解码 - 将解码结果分配给CCD_ 3。通过这种方式,分配了
self
的所有属性