| Xcode | Minimun Deployments | Version |
|---|---|---|
| Xcode15+ | iOS13+ / macOS11+ | 1.0+ |
| Xcode15- | iOS13- / macOS11- | 0.3.3 |
The project objective is to enhance the usage experience of the Codable protocol using the macro provided by Swift 5.9 and to address the shortcomings of various official versions.
- Default value
- Basic type automatic convertible, between
StringBoolNumberetc. - Custom multiple
CodingKey - Nested Dictionary
CodingKey - Automatic compatibility between camel case and snake case
- Convenience
Codablesubclass - Transformer
pod 'CodableWrapper', :git => 'https://github.com/winddpan/CodableWrapper.git'
https://github.com/winddpan/CodableWrapper
@CodablestructBasicModel{vardefaultVal:String="hello world"vardefaultVal2:String=Bool.random()?"hello world":""letstrict:StringletnoStrict:String?letautoConvert:Int?@CodingKey("hello")varhi:String="there"@CodingNestedKey("nested.hi")@CodingTransformer(StringPrefixTransform("HELLO -> "))varcodingKeySupport:String@CodingNestedKey("nested.b")varnestedB:StringvartestGetter:String{
nestedB
}}finalclassCodableWrapperTests:XCTestCase{func testBasicUsage()throws{letjsonStr=""" {"strict": "value of strict","autoConvert": "998","nested": {"hi": "nested there","b": "b value" } }"""letmodel=tryJSONDecoder().decode(BasicModel.self, from: jsonStr.data(using:.utf8)!)XCTAssertEqual(model.defaultVal,"hello world")XCTAssertEqual(model.strict,"value of strict")XCTAssertEqual(model.noStrict,nil)XCTAssertEqual(model.autoConvert,998)XCTAssertEqual(model.hi,"there")XCTAssertEqual(model.codingKeySupport,"HELLO -> nested there")XCTAssertEqual(model.nestedB,"b value")letencoded=tryJSONEncoder().encode(model)letdict=tryJSONSerialization.jsonObject(with: encoded)as![String:Any]XCTAssertEqual(model.defaultVal,dict["defaultVal"]as!String)XCTAssertEqual(model.strict,dict["strict"]as!String)XCTAssertNil(dict["noStrict"])XCTAssertEqual(model.autoConvert,dict["autoConvert"]as?Int)XCTAssertEqual(model.hi,dict["hello"]as!String)XCTAssertEqual("nested there",(dict["nested"]as![String:Any])["hi"]as!String)XCTAssertEqual(model.nestedB,(dict["nested"]as![String:Any])["b"]as!String)}}Auto conformance
Codableprotocol if not explicitly declared// both below works well @CodablestructBasicModel{}@CodablestructBasicModel:Codable{}
Default value
@CodablestructTestModel{letname:Stringvarbalance:Double=0} // { "name": "jhon" }
Basic type automatic convertible, between
StringBoolNumberetc.@CodablestructTestModel{letautoConvert:Int?} // { "autoConvert": "998" }
Automatic compatibility between camel case and snake case
@CodablestructTestModel{varuserName:String=""} // { "user_name": "jhon" }
Member Wise Init
@CodablepublicstructTestModel{publicvaruserName:String="" // Automatic generated publicinit(userName:String=""){self.userName = userName }}
@Codable(wiseInit:false)publicstructTestModel{publicvaruserName:String="" // Disable WiseInit Automatic generated }
Custom
CodingKeys@CodablestructTestModel{@CodingKey("u1","u2","u9")varuserName:String=""} // { "u9": "jhon" }
Ignored propery on encode and decode
structNonCodable{}@CodablestructTestModel{@CodingKeyIgnoredvarnonCodable:NonCodable?}
Custom
CodingKeys innested dictionary@CodablestructTestModel{@CodingNestedKey("data.u1","data.u2","data.u9")varuserName:String=""} // { "data": {"u9": "jhon"} }
Automatic generate
Codableclass's subclassinit(from:)andencode(to:)super calls@CodableclassBaseModel{letuserName:String}@CodableSubclassclassSubModel:BaseModel{letage:Int} // {"user_name": "jhon", "age": 22}
Transformer between in
Codable/NonCodablemodelstructDateWrapper{lettimestamp:TimeIntervalvardate:Date{Date(timeIntervalSince1970: timestamp)}init(timestamp:TimeInterval){self.timestamp = timestamp }staticvartransformer=TransformOf<DateWrapper,TimeInterval>(fromJSON:{DateWrapper(timestamp: $0 ??0)}, toJSON:{ $0.timestamp })}@CodablestructDateModel{@CodingTransformer(DateWrapper.transformer)vartime:DateWrapper?=DateWrapper(timestamp:0)@CodingTransformer(DateWrapper.transformer)vartime1:DateWrapper=DateWrapper(timestamp:0)@CodingTransformer(DateWrapper.transformer)vartime2:DateWrapper?}classTransformTest:XCTestCase{func testDateModel()throws{letjson=""" {"time": 12345}"""letmodel=tryJSONDecoder().decode(DateModel.self, from: json.data(using:.utf8)!)XCTAssertEqual(model.time?.timestamp,12345)XCTAssertEqual(model.time?.date.description,"1970-01-01 03:25:45 +0000")letencode=tryJSONEncoder().encode(model)letjsonObject=tryJSONSerialization.jsonObject(with: encode, options:[])as![String:Any]XCTAssertEqual(jsonObject["time"]as!TimeInterval,12345)}}