gpt4 book ai didi

swift - 基于嵌套类型属性反序列化 JSON 数组

转载 作者:行者123 更新时间:2023-11-28 05:37:18 29 4
gpt4 key购买 nike

考虑这个示例 JSON:

{
"sections": [{
"title": "Sign up",
"rows": [
{
"type": "image",
"imageURL": "https://example.com/image.jpg"
},
{
"type": "textField",
"value": "",
"placeholder": "Username"
},
{
"type": "textField",
"placeholder": "password"
},
{
"type": "textField",
"placeholder": "confirmPassword"
},
{
"type": "button",
"placeholder": "Register!"
}
]
}]
}

假设我想将上面的 JSON 解析为以下模型(我知道它不会编译,因为 Row 协议(protocol)与 Decodable 不对应):

enum RowType: String, Codable {
case textField
case image
case button
}

protocol Row: Codable {
var type: RowType { get }
}

struct TextFieldRow: Row {
let type: RowType
let placeholder: String
let value: String

enum CodingKey: String {
case type
case placeholder
case value
}
}

struct ImageRow: Row {
let type: RowType
let imageURL: URL

enum CodingKey: String {
case type
case imageURL
}
}

struct ButtonRow: Row {
let type: RowType
let title: String

enum CodingKey: String {
case type
case title
}
}

struct Section: Codable {
let rows: [Row]
let title: String

enum CodingKey: String {
case rows
case title
}
}

struct Response: Codable {
let sections: [Section]

enum CodingKey: String {
case sections
}
}


// Parsing the response using the Foundation JSONDecoder
let data: Data // From network
let decoder = JSONDecoder()
do {
let response = try decoder.decode(Response.self, from: data)
} catch {
print("error: \(error)")
}

有没有办法让 Codable 上面的 Swift 代码兼容?我知道您可以手动解决这个问题,首先获取每个 Rowtype 字符串,然后创建正确类型的 Row 模型并更改它们从结构到类,并让 Row 协议(protocol)成为一个父类(super class)。但有没有一种方法可以减少体力劳动?

最佳答案

使用具有关联值的枚举是最佳选择:

考虑这个枚举:

enum Row: Decodable {
case textField(TextFieldRow)
case image(ImageRow)
// and other cases

case unknown

enum CodingKeys: String, CodingKey {
case type
}

public init(from decoder: Decoder) throws {
do {
let selfContainer = try decoder.singleValueContainer()
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
let type = try typeContainer.decode(String.self, forKey: .type)

switch type {
case "textField": self = .textField( try selfContainer.decode(TextFieldRow.self) )
case "Image": self = .image( try selfContainer.decode(ImageRow.self) )
// and other cases
default: self = .unknown
}
}
}
}

有了这些变化:

struct TextFieldRow: Decodable {
let placeholder: String?
let value: String?
}

struct ImageRow: Decodable {
let imageURL: URL
}

// and so on

现在这将像魅力一样解码:

// Minmal testing JSON
let json = """
[
{
"type": "image",
"imageURL": "https://example.com/image.jpg"
},
{
"type": "textField",
"value": "",
"placeholder": "Username"
},
{
"type": "textField",
"placeholder": "password"
}
]
""".data(using: .utf8)!
let decoder = JSONDecoder()
print( try! decoder.decode([Row].self, from: json) )

您现在可以将您需要的任何其他案例添加到解码器以构建您的应用程序构建器应用程序。

关于swift - 基于嵌套类型属性反序列化 JSON 数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58256964/

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