SuperCodable

源自 Foundation

struct AStudent: Codable {
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        self.aID = try container.decode(String.self, forKey: .aID)
        self.aName = try container.decode(String.self, forKey: .aName)
        let gradeDecoded = try container.decode(Double.self, forKey: .aGrade)
        self.AGrede = Int(gradeDecoded)
    }

    enum CodingKeys: String, CodingKey {
        case aName = "name"
        case aGrade = "grade"
        case aID = "id"
    }

    var aID: String
    var aName: String
    var AGrede: Int

    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(aID, forKey: .aID)
        try container.encode(Double(AGrede), forKey: .aGrade)
        try container.encode(aName, forKey: .aName)
    }
}

到 SuperCodable

struct Student: SuperCodable {
    @Keyed
    var id: String
    
    @Keyed("name") 
    var aName: String
    
    @KeyedTransform("grade", doubleTransform)
    var AGrade: Int
}

let doubleTransform = SCTransformOf<Int, Double> {
    (double) -> Int in
    Int(double)
} toEncoder: { (int) -> Double in
    Double(int)
}

甚至随机的后端类型

struct AnyValueJSON: SuperCodable {
    @KeyedTransform(IDTransform)
    var id:Int
}

 let data =
    #"""
    [
        {
            "id": "0",
        },
        {
            "id": 1,
        },
        {
            "id": "abc",
        },
        {
            "id": true,
        },
    ]
    """#.data(using: .utf8)!
let sut = try! JSONDecoder().decode([AnyValueJSON].self, from: data)
XCTAssertEqual(sut.count, 4)
XCTAssertEqual(sut.map(\.id), [0, 1, 0, 1])

可以在 Tests/SuperCodableTests/AnyValueDecode.swift 中找到

特性

已知副作用

已知缺陷

为什么

基本上,反射无法在 init(from decoder:) throws 期间修改对象值,因为我们从 self.init() 创建对象

其他注意事项

已知问题