swift - 在 Swift 中合并 Encodable

标签 swift codable

我有以下 Swift 结构

struct Session: Encodable {
    let sessionId: String
}
struct Person: Encodable {
    let name: String
    let age: Int
}

let person = Person(name: "Jan", age: 36)
let session = Session(sessionId: "xyz")

我需要编码为具有这种格式的 json 对象:

{
  "name": "Jan",
  "age": 36,
  "sessionId": "xyz"
}

其中 Session 的所有键都合并到 Person 的键中

我考虑过使用带有自定义 Encodable 实现的容器结构,其中我使用了 SingleValueEncodingContainer 但它显然只能编码一个值

struct RequestModel: Encodable {
    let session: Session
    let person: Person

    public func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        try container.encode(person)
        // crash
        try container.encode(session)
    }
}

let person = Person(name: "Jan", age: 36)
let session = Session(sessionId: "xyz")
let requestModel =  RequestModel(session: session, person: person)

let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted

let data = try encoder.encode(requestModel)
let json = String(data: data, encoding: .utf8)!

print(json)

我无法更改 json 格式,因为它是固定的网络 API。我可以将 sessionId 作为 Person 的属性,但我想避免这种情况,因为它们是不相关的模型。

另一种方法是让 RequestModelSessionPerson 中复制所有属性,如下所示,但这不是很好,因为我的真正的结构有更多的属性。

struct RequestModel: Encodable {
    let sessionId: String
    let name: String
    let age: Int

    init(session: Session, person: Person) {
        sessionId = session.sessionId
        name = person.name
        age = person.age
    }
}

最佳答案

调用每个可编码对象的encode(to:),而不是singleValueContainer()。 无需定义额外的 CodingKeys 即可将多个可编码对象合并为一个可编码对象。

struct RequestModel: Encodable {
    let session: Session
    let person: Person

    public func encode(to encoder: Encoder) throws {
        try session.encode(to: encoder)
        try person.encode(to: encoder)
    }
}

关于swift - 在 Swift 中合并 Encodable,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52984142/

相关文章:

ios - 包含带有自定义单元格的 Collection View 的 UIViewController xib 文件

swift - 如何为 if 语句分配两个条件

ios - 禁用 SpriteKit 中 SKNode 的旋转

swift - AddGesture 在 Swift 3 中有什么不同?

ios - 受密码保护的 UITextField 上的大写锁定图像

swift - 在 swift iOS 中出现意外值时,如何将 nil 设置为可编码枚举

json - swift 4.2 : Type 'T' does not conform to protocol 'Decodable'

swift - Xcode 9.3 (Swift 4.1) 中的 Codable 'has no initializers'

swift - Codable API 能否用于解码使用 NSKeyedArchiver.archivedData 编码的数据?

swift - 可选键的默认枚举值