我希望有一个可以通过常规Codable协议或字典实例化的Struct(现有代码需要字典实例化)。
我在操场上有此代码,但是我不确定在第二个需要Dictionary的init中该怎么做。如何用字典制作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
...
答案 0 :(得分:1)
扩展您的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)
}
}
答案 1 :(得分:0)
您在正确的道路上。
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)
我所做的只是:
ResponseModel
的对象self
。这样就分配了self
的所有属性。