gpt4 book ai didi

ios - 是否有可能有一个符合相同协议(protocol)的结构数组也支持 Codable?

转载 作者:行者123 更新时间:2023-12-01 19:38:05 25 4
gpt4 key购买 nike

我已经设置了以下协议(protocol),并且有 2 个结构,然后符合此协议(protocol):

protocol ExampleProtocol: Decodable {
var name: String { get set }
var length: Int { get set }
}

struct ExampleModel1: ExampleProtocol {
var name: String
var length: Int
var otherData: Array<String>
}

struct ExampleModel2: ExampleProtocol {
var name: String
var length: Int
var dateString: String
}

我想反序列化从服务器接收到的一些 JSON 数据,并且我知道它将在数组中返回 ExampleModel1 和 ExampleModel2 的混合:
struct ExampleNetworkResponse: Decodable {
var someString: String
var modelArray: Array<ExampleProtocol>
}

无论如何使用 Codable 方法并轻松支持这两种模型?还是我需要手动反序列化每个模型的数据?

编辑1:

符合 Decodable 的结构,仍然给出相同的结果:
struct ExampleModel1: ExampleProtocol, Decodable {

enum CodingKeys: String, CodingKey {
case name, length, otherData
}

init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.name = try container.decode(String.self, forKey: .name)
self.length = try container.decode(Int.self, forKey: .length)
self.otherData = try container.decode(Array<String>.self, forKey: .otherData)
}

var name: String
var length: Int
var otherData: Array<String>
}

struct ExampleModel2: ExampleProtocol, Decodable {

enum CodingKeys: String, CodingKey {
case name, length, dateString
}

init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.name = try container.decode(String.self, forKey: .name)
self.length = try container.decode(Int.self, forKey: .length)
self.dateString = try container.decode(String.self, forKey: .dateString)
}

var name: String
var length: Int
var dateString: String
}

struct ExampleNetworkResponse: Decodable {
var someString: String
var modelArray: Array<ExampleProtocol>
}

最佳答案

如果您的ExampleProtocol数量有限s 并且你需要在同一个数组中有不同类型的 ExampleProtocols,那么你可以为 ExampleProtocol 创建一个持有者并将其用于解码/编码。

ExampleHolder 可以在一个数组中保存所有可能的 Decodable ExampleProtocol 类型。所以解码器 init 不需要有那么多 if-else 范围,并且将来更容易添加。

建议将 ExampleHolder 保留为私有(private)结构。所以不可能在文件之外访问它,甚至不能在 ExampleNetworkResponse 之外访问它。

enum ExampleNetworkResponseError: Error {
case unsupportedExampleModelOnDecoding
}

private struct ExampleHolder: Decodable {
let exampleModel: ExampleProtocol

private let possibleModelTypes: [ExampleProtocol.Type] = [
ExampleModel1.self,
ExampleModel2.self
]

init(from decoder: Decoder) throws {
for type in possibleModelTypes {
if let model = try? type.init(from: decoder) {
exampleModel = model
return
}
}

throw ExampleNetworkResponseError.unsupportedExampleModelOnDecoding
}
}

struct ExampleNetworkResponse: Decodable {
var someString: String
var modelArray: Array<ExampleProtocol>

enum CodingKeys: String, CodingKey {
case someString, modelArray
}

init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
someString = try container.decode(String.self, forKey: .someString)
let exampleHolderArray = try container.decode([ExampleHolder].self, forKey: .modelArray)
modelArray = exampleHolderArray.map({ $0.exampleModel })
}
}

––––––––––––––––––––––––––––––––––––––

如果在一个响应中只能有一种 ExampleProtocol然后在数组中:

struct ExampleNetworkResponse2<ModelArrayElement: ExampleProtocol>: Decodable {
var someString: String
var modelArray: Array<ModelArrayElement>
}

用法:

let decoder = JSONDecoder()
let response = try decoder.decode(
ExampleNetworkResponse2<ExampleModel1>.self,
from: dataToDecode
)

关于ios - 是否有可能有一个符合相同协议(protocol)的结构数组也支持 Codable?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59270672/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com