HandyJSON第三方库的日常使用与错误记录
一、错误提示
1、更新Xcode10.2,Swift5.0出现错误提示
Undefined symbols for architecture x86_64:
"_swift_getFieldAt", referenced from:
HandyJSON.Metadata.Class._propertyDescriptionsAndStartPoint() -> ([HandyJSON.Property.Description], Swift.Int32?)? in Metadata.o
HandyJSON.Metadata.Struct.propertyDescriptions() -> [HandyJSON.Property.Description]? in Metadata.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
更改 podfile
pod 'HandyJSON', '5.0.0-beta'
如果不行的话 更新本地cocoapods的spec资源配置信息。
pod repo update
笔者是使用的第二种方法进行解决的。
二、HandyJSON的使用
1、基本操作:序列化与反序列化
class BasicTypes: HandyJSON { var int: Int = 2 var doubleOptional: Double? var stringImplicitlyUnwrapped: String! required init() {} } //反序列化 let jsonString = "{\"doubleOptional\":1.1,\"stringImplicitlyUnwrapped\":\"hello\",\"int\":1}" if let object = BasicTypes.deserialize(from: jsonString) { print(object.int) print(object.doubleOptional!) print(object.stringImplicitlyUnwrapped!) } print("-----------------------------") //序列化 let objectOne = BasicTypes() objectOne.int = 1 objectOne.doubleOptional = 2.2 objectOne.stringImplicitlyUnwrapped = "world" print(objectOne.toJSON()!) print("-----------------------------") print(objectOne.toJSONString()!) print("-----------------------------") print(objectOne.toJSONString(prettyPrint: true)!) print("-----------------------------")
2、基本数据类型
class BasicTypesTwo: HandyJSON { var bool: Bool = true var intOptional: Int? var doubleImplicitlyUnwrapped: Double! var anyObjectOptional: Any? var arrayInt: Array<Int> = [] var arrayStringOptional: Array<String>? var setInt: Set<Int>? var dictAnyObject: Dictionary<String, Any> = [:] var nsNumber = 2 var nsString: NSString? required init() {} } let object = BasicTypesTwo() object.intOptional = 1 object.doubleImplicitlyUnwrapped = 1.1 object.anyObjectOptional = "StringValue" object.arrayInt = [1, 2] object.arrayStringOptional = ["a", "b"] object.setInt = [1, 2] object.dictAnyObject = ["key1": 1, "key2": "stringValue"] object.nsNumber = 2 object.nsString = "nsStringValue" let jsonString = object.toJSONString()! if let object = BasicTypesTwo.deserialize(from: jsonString) { print(object.arrayStringOptional!) print(object.dictAnyObject) //.... }
3、指定解析路径
HandyJSON支持指定从哪个具体路径开始解析,反序列化到Model。
class Cat: HandyJSON { var id: Int64! var name: String! required init() {} } let json = "{\"code\":200,\"msg\":\"success\",\"data\":{\"cat\":{\"id\":12345,\"name\":\"Kitty\"}}}" if let cat = Cat.deserialize(from: json, designatedPath: "data.cat") { print(cat.name!) print(cat.id!) }
4、组合对象
注意,如果Model的属性不是基本类型或集合类型,那么它必须是一个服从HandyJSON
协议的类型。
如果是泛型集合类型,那么要求泛型实参是基本类型或者服从HandyJSON
协议的类型。
class Component: HandyJSON { var aInt: Int? var aString: String? required init() {} } class Composition: HandyJSON { var aInt: Int? var comp1: Component? var comp2: Component? required init() {} } let jsonString = "{\"num\":12345,\"comp1\":{\"aInt\":1,\"aString\":\"aaaaa\"},\"comp2\":{\"aInt\":2,\"aString\":\"bbbbb\"}}" if let composition = Composition.deserialize(from: jsonString) { print(composition.comp1?.aString! as Any) print(composition.comp2?.aInt! as Any) }
5、继承
如果子类要支持反序列化,那么要求父类也服从HandyJSON
协议。
let jsonString = "{\"id\":12345,\"color\":\"black\",\"name\":\"cat\"}" if let cat = Cat.deserialize(from: jsonString) { print(cat) }
6、JSON数组
如果JSON的第一层表达的是数组,可以转化它到一个Model数组。
let jsonArrayString: String? = "[{\"name\":\"Bob\",\"id\":\"1\"}, {\"name\":\"Lily\",\"id\":\"2\"}, {\"name\":\"Lucy\",\"id\":\"3\"}]" if let cats = [Cat].deserialize(from: jsonArrayString) { cats.forEach({ (cat) in print(cat?.name! as Any) print(cat?.id! as Any) }) }
7、字典 -> 模型
class BasicTypes: HandyJSON { var int: Int = 2 var doubleOptional: Double? var stringImplicitlyUnwrapped: String! required init() {} } var dict = [String: Any]() dict["doubleOptional"] = 1.1 dict["stringImplicitlyUnwrapped"] = "hello" dict["int"] = 1 if let object = BasicTypes.deserialize(from: dict) { print(object.doubleOptional as Any) print(object.stringImplicitlyUnwrapped as Any) print(object.int) }
8、自定义解析规则
开发中某些关键字段为避免混淆,可以使用其他关键字替换
class Person: HandyJSON { var ID: Int64! var username: String! var parents: (String, String)? required init() {} func mapping(mapper: HelpingMapper) { mapper <<< self.ID <-- "cat_id" mapper <<< self.username <-- "name" } } let jsonString = "{\"cat_id\":12345,\"name\":\"Kitty\",\"parent\":\"Tom/Lily\",\"friend\":{\"id\":54321,\"name\":\"Lily\"}}" if let person = Person.deserialize(from: jsonString) { print(person.ID as Any) print(person.username as Any) }
9、日常开发接口测试
class CarList : HandyJSON { var ID : String! var pic : String? var comname : String? var address : String? required init() { } func mapping(mapper: HelpingMapper) { mapper <<< self.ID <-- "id" } } //返回json样式 //成功: //{ // "status": 1, // "result": [{ // "id": "1", // "pic": "图片地址", // "comname": "汽车美容店", // "address": "广东省" // }] //} //失败: //{ // "status":0, // "msg":"获取失败,请稍后重试..." //} let dict = ["pagesize":10,"page":1,"address":""] as [String : Any] NANetworkHandler.shareInstance.postRequest("https://******/submit_ajax.ashx?action=APP_GetBusiness", params: dict, success: { (response) in let resultJson = response if resultJson["status"] as! Int == 1 { if let carArr = [CarList].deserialize(from: (resultJson["result"] as! Array) ) { carArr.forEach({ (car) in print("\(String(describing: car?.ID))") print("\(String(describing: car?.pic))") print("\(String(describing: car?.comname))") print("\(String(describing: car?.address))") }) } }else if response["status"] as! Int == 0 { //... } }) { ( err) in //... }
附:
Alamofire简单封装
import UIKit import Alamofire public typealias Success = (_ dict : [String:Any])->() public typealias Failure = (_ error : Error)->() class NANetworkHandler : NSObject { static var shareInstance : NANetworkHandler { struct Share { static let instance = NANetworkHandler() } return Share.instance } //GET请求 func getRequest( _ urlString: String, params: Parameters? = nil, success: @escaping Success, failure: @escaping Failure) { request(urlString, params: params, method: .get, success, failure) } //POST请求 func postRequest( _ urlString: String, params: Parameters? = nil, success: @escaping Success, failure: @escaping Failure) { request(urlString, params: params, method: .post, success, failure) } //图片上传 func upLoadImageRequest(urlString : String, params:[String:String], imgArr:[UIImage], name: [String],success : @escaping Success, failure : @escaping Failure){ let headers = ["content-type":"multipart/form-data"] Alamofire.upload( multipartFormData: { multipartFormData in if imgArr.count == 0 { return } //此处循环上传多占图片 for (index, value) in imgArr.enumerated() { let imageData = UIImage.jpegData(value)(compressionQuality: 0.5)! let formatter = DateFormatter() formatter.dateFormat = "yyyyMMddHHmmss" let str = formatter.string(from: Date()) let fileName = str+"\(index)"+".jpg" multipartFormData.append(imageData, withName: "imageUpload", fileName: fileName, mimeType: "image/png") } }, to: urlString, headers: headers, encodingCompletion: { encodingResult in switch encodingResult { case .success(let upload, _, _): upload.responseJSON { response in if let value = response.result.value as? [String: Any] { success(value as [String : Any]) } } break case .failure(let err): failure(err) break } } ) } private func request(_ urlString: String, params:Parameters? = nil, method:HTTPMethod, _ success:@escaping Success, _ failure:@escaping Failure){ let manager = Alamofire.SessionManager.default manager.session.configuration.timeoutIntervalForRequest = 15 manager.request(urlString, method: method, parameters: params, encoding: JSONEncoding.default, headers: nil).responseJSON { (response) in switch response.result { case .success: if let value = response.result.value as? [String: Any] { success(value as [String : Any]) } break case .failure(let err): failure(err) break } } } }