Skip to content

Repository files navigation

Requirements

XcodeMinimun DeploymentsVersion
Xcode15+iOS13+ / macOS11+1.0+
Xcode15-iOS13- / macOS11-0.3.3

About

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.

Feature

  • Default value
  • Basic type automatic convertible, between StringBoolNumber etc.
  • Custom multiple CodingKey
  • Nested Dictionary CodingKey
  • Automatic compatibility between camel case and snake case
  • Convenience Codable subclass
  • Transformer

Installation

CocoaPods

pod 'CodableWrapper', :git => 'https://github.com/winddpan/CodableWrapper.git'

Swift Package Manager

https://github.com/winddpan/CodableWrapper

Example

@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)}}

Macro usage

@Codable

  • Auto conformance Codable protocol 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 StringBoolNumber etc.

    @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
    }

@CodingKey

  • Custom CodingKeys

    @CodablestructTestModel{@CodingKey("u1","u2","u9")varuserName:String=""}
    // { "u9": "jhon" }

@CodingKeyIgnored

  • Ignored propery on encode and decode

    structNonCodable{}@CodablestructTestModel{@CodingKeyIgnoredvarnonCodable:NonCodable?}

@CodingNestedKey

  • Custom CodingKeys in nested dictionary

    @CodablestructTestModel{@CodingNestedKey("data.u1","data.u2","data.u9")varuserName:String=""}
    // { "data": {"u9": "jhon"} }

@CodableSubclass

  • Automatic generate Codable class's subclass init(from:) and encode(to:) super calls

    @CodableclassBaseModel{letuserName:String}@CodableSubclassclassSubModel:BaseModel{letage:Int}
    // {"user_name": "jhon", "age": 22}

@CodingTransformer

  • Transformer between in Codable / NonCodable model

    structDateWrapper{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)}}

Star History

Star History Chart

About

@codingkey("encoder", "decoder") var cool: Bool = true

Topics

Resources

Stars

388 stars

Watchers

6 watching

Forks

Releases

Packages

Contributors

Languages