func testBaseCodable() { let deJsonStr = """ { "id": "123456", "name": "小明", "grade": 1 } """ let deData = deJsonStr.data(using: String.Encoding.utf8)! do { let decoder = JSONDecoder.init() let object = try decoder.decode(Student1.self, from: deData) DLog(object) } catchlet error as NSError { DLog("解码失败:\(error.debugDescription)") }
let student = Student1.init(id: "127182781278", name: "小红", grade: 3) do { let jsonData2 = try JSONEncoder.init().encode(student) let jsonString = String.init(data: jsonData2, encoding: String.Encoding.utf8) DLog(jsonString!) } catchlet error as NSError { DLog("编码失败:\(error.debugDescription)") } }
上述代码中我们为模型实现了Codable协议.在实际使用时并不需要这么麻烦,因为Swift标准库中的类型,比如String,Int,Double和 Foundation 框架中Data,Date,URL都是默认支持Codable协议的,所以如果你的模型使用的都是Swift标准库中的类型,那么只需声明支持协议即可。如下:
classPerson1: Codable { var name: String="" var age: Int=0 var motto: String="" var sex: Bool=true enumCodingKeys: String, CodingKey { case name ="_name" case age ="_age" case motto ="motto" case sex ="sex" } }
classPerson2: Codable { var name: String="" var age: Int=0 var motto: String="" var sex: Bool=true enumCodingKeys: String, CodingKey { case name case age } }
typeMismatch(Swift.Int, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "age", intValue: nil)], debugDescription: "Expected to decode Int but found a string/data instead.", underlyingError: nil))
typeMismatch(Swift.Bool, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "sex", intValue: nil)], debugDescription: "Expected to decode Bool but found a number instead.", underlyingError: nil))
classTimeLine: Codable{ // 服务端使用字符串枚举 enum TimeLineTemplate: String, Codable { case video = "video" case pic = "pic" case link = "link" } //服务端使用整型枚举 enum Gender: Int, Codable { case female = 0 case male = 1 } var feedID: String var template: TimeLineTemplate var gender: Gender }
classPerson5: Codable { var name: String="" var age: Int=0 var motto: String="" var sex: Bool=true var position: CLLocationCoordinate2D? privateenumCodingKeys: String, CodingKey { case name ="_name" case age ="_age" case motto case sex case position ="position" } //自己实现Codable协议.缺点:麻烦,编码,解码都需要实现. privateenumPositionCodingKeys: String, CodingKey { case latitude case longitude } init(name: String) { self.name = name }
classPerson4: Codable { var name: String="" var age: Int=0 var motto: String="" var sex: Bool=true var id: String="" var position: CLLocationCoordinate2D? { get { return _position ==nil?nil : CLLocationCoordinate2D.init(latitude: _position!.latitude, longitude: _position!.longitude) } set { if newValue ==nil { _position =nil } else { _position = _CLLocationCoordinate2D.init(latitude: newValue!.latitude, longitude: newValue!.longitude) } } } privatestruct_CLLocationCoordinate2D: Codable { var latitude: CLLocationDegrees var longitude: CLLocationDegrees
init(latitude: CLLocationDegrees, longitude: CLLocationDegrees) { self.latitude = latitude self.longitude = longitude } } privatevar _position: _CLLocationCoordinate2D? privateenumCodingKeys: String, CodingKey { case name ="_name" case age ="_age" case motto case sex case _position ="position" } }
解码失败:ErrorDomain=NSCocoaErrorDomain Code=4865 "No value associated with key CodingKeys(stringValue: "grade", intValue: nil) ("grade")." UserInfo={NSDebugDescription=No value associated with key CodingKeys(stringValue: "grade", intValue: nil) ("grade")., NSCodingPath=( )}
1 2 3
解码失败:ErrorDomain=NSCocoaErrorDomain Code=4865 "Expected Int value but found null instead." UserInfo={NSCodingPath=( "CodingKeys(stringValue: \"grade\", intValue: nil)" ), NSDebugDescription=Expected Int value but found null instead.}
由于这个类实例的内存布局可能会变,所以官方文档中有提到”HandyJSON is totally depend on the memory layout rules infered from Swift runtime code. We are watching it and will follow every bit if it changes.“.
classHJPerson: HandyJSON { //服务端使用整型枚举 enumHobbit: Int, HandyJSONEnum { case none =-1 case basketball =0 case football =1 } enumMusic: String, HandyJSONEnum { case none case classic case modern } var name: String="" var age: Int=0 var motto: String="" var sex: Bool=true var height: Float=0 var id: String="" var hobbit: Hobbit= .none var music: Music= .none requiredinit() { } //名称不匹配时 funcmapping(mapper: HelpingMapper) { mapper.specify(property: &name, name: "_name") } }
classHJTeacher: HJPerson { var course: String="" }
structStudent2: HandyJSON { init() { id ="" name ="" grade =0 } var id: String var name: String var grade: Int }
classOMPerson: Mappable { //服务端使用整型枚举 enumHobbit: Int { case none =-1 case basketball =0 case football =1 } enumMusic: String { case none case classic case modern } var name: String="" var age: Int=0 var motto: String="" var sex: Bool=true var height: Float=0 var id: String="" var hobbit: Hobbit= .none var music: Music= .none requiredinit?(map: Map) { } funcmapping(map: Map) { name <- map["_name"] age <- map["age"] motto <- map["motto"] sex <- map["sex"] height <- map["height"] id <- map["id"] hobbit <- map["hobbit"] music <- map["music"] } }