首页 > 解决方案 > 多个可编码实现

问题描述

假设我有一个对象 ,Game它包含三个属性scorefirstNamelastName

 class Game: Encodable {

    var firstName: String
    var lastName: String
    var score: Int

    enum CodingKeys: String, CodingKey {
        case firstName
        case lastName
        case score
    }

    func encode(to encoder: Encoder) throws {
        var encoder = encoder.container(keyedBy: CodingKeys.self)
        try? encoder.encode(self.firstName, forKey: .firstName)
        try? encoder.encode(self.lastName, forKey: .lastName)
        try? encoder.encode(self.score, forKey: .score)
    }
 }

假设我想将它保存到磁盘,我可以使用JSONEncoder

let game = Game(firstName: "John", lastName: "Smith", score: 42)
let data = try JSONEncoder().encode(game)
{
    firstName: "John",
    lastName: "Smith",
    score: 42
}

现在我希望用户能够自己生成 JSON 并将其共享给任何应用程序,但出于隐私原因,我想省略姓氏,如何encode(to encoder: Encoder)为一种类型创建两个实现?

示例输出:

{
    firstName: "John",
    score: 42
}

标签: swiftcodable

解决方案


有一些选择。除了 Sandeep 的带有 Bool 标志的解决方案之外,多态性可能是另一种解决方案:

final class ShareableGame: Game {

  init(_ game: Game) {
    super.init(firstName: game.firstName,
               lastName: game.lastName,
               score: game.score)
  }

  override func encode(to encoder: Encoder) throws {
    var encoder = encoder.container(keyedBy: CodingKeys.self)
    try? encoder.encode(self.firstName, forKey: .firstName)
    try? encoder.encode(self.score, forKey: .score)
  }

}

let game = Game(firstName: "John", lastName: "Smith", score: 42)
let shareableGame = ShareableGame(game)
let shareableGameData = try JSONEncoder().encode(shareableGame)
print(String(bytes: shareableGameData, encoding: .utf8)!)

// {"firstName":"John","score":42}

(假设 Game 类的定义与此类似:)

class Game: Encodable {

  let firstName: String
  let lastName: String
  let score: Int

  init(firstName: String, lastName: String, score: Int) {
    self.firstName = firstName
    self.lastName = lastName
    self.score = score
  }

  /*
   encode(to:) throws can be omitted, since the default     
   implementation is exactly as expected.
  */

  enum CodingKeys: String, CodingKey {
    // Cannot be omitted, since it's used in subclasses.

    case firstName
    case lastName
    case score

  }

}

推荐阅读