swift 解码失败时在嵌套枚举中设置结构变量

x33g5p2x  于 2023-01-12  发布在  Swift
关注(0)|答案(1)|浏览(162)

我有一个简单的结构,我需要设置一个标志枚举解码失败。不确定现在这样做。

struct TestStruct: Codable {
  let testEnum: TestEnum

  let failDecode: Bool

}

extension TestStruct {

   enum TestEnum: String, Codable {

      case val1 = "VAL1"

      case val2 = "VAL2"
      public init(from decoder: Decoder) throws {
         let testState = try decoder.singleValueContainer().decode(String.self)
         switch testState{
         case "VAL1": self = .val1
         case "VAL2": self = .val2
         default: TestStruct.failDecode = true   // fail compile here
         }
      }

   }

}

如何在解码失败时设置failDecode标志?

eyh26e7m

eyh26e7m1#

对于TestStruct,需要自定义init(from:)初始值设定项。对于TestEnum,不需要自定义init(from:)初始值设定项。

struct TestStruct {
    let testEnum: TestEnum
    let failDecode: Bool
}

extension TestStruct {
    enum TestEnum: String, Codable {
        case val1 = "VAL1"
        case val2 = "VAL2"
    }
}

extension TestStruct: Decodable {
    public init(from decoder: Decoder) throws {
        do {
            testEnum = try TestEnum(from: decoder)
            failDecode = false
        } catch {
            failDecode = true

            // You must initialize testEnum to some valid value,
            // even though you couldn't decode it!
            testEnum = .val1
        }
    }
}

如果你想要Codable一致性,而不仅仅是Decodable一致性,那么你还需要提供一个匹配的encode(to:)方法。

extension TestStruct: Encodable {
    func encode(to encoder: Encoder) throws {
        try testEnum.encode(to: encoder)
    }
}

(Note CodableDecodable & Encodable的别名,因此提供单独的DecodableEncodable一致性与提供单个Codable一致性相同。
我忽略了encode(to:)实现中的failDecode标志,但是如果设置了failDecode,您可能希望编码一个非法值,这个版本在failDecode为真时编码nil:

extension TestStruct: Encodable {
    func encode(to encoder: Encoder) throws {
        if failDecode {
            try Optional<TestEnum>.none.encode(to: encoder)
        } else {
            try testEnum.encode(to: encoder)
        }
    }
}

相关问题