将swift对象转换为JSONstring

我有这样的课程:

class MyDate { var year : String = "" var month : String = "" var day : String = "" init(year : String , month : String , day : String) { self.year = year self.month = month self.day = day } } 

 class Lad { var firstName : String = "" var lastName : String = "" var dateOfBirth : MyDate? init(firstname : String , lastname : String , dateofbirth : MyDate) { self.firstName = firstname self.lastName = lastname self.dateOfBirth = dateofbirth } } 

 class MainCon { func sendData() { let myDate = MyDate(year: "1901", month: "4", day: "30") let obj = Lad(firstname: "Markoff", lastname: "Chaney", dateofbirth: myDate) let api = ApiService() api.postDataToTheServer(led: obj) } } 

 class ApiService { func postDataToTheServer(led : Lad) { // here i need to json } } 

我想将一个Lad对象转换成如下所示的JSONstring:

{“firstName”:“Markoff”,“lastName”:“Chaney”,“dateOfBirth”:{“year”:“1901”,“month”:“4”,“day”:“30”}}

编辑 – 10/31/2017:这个答案大多适用于Swift 3和可能更早的版本。 截至2017年底,我们现在有了Swift 4,您应该使用Encodable和Decodable协议来转换表示之间的数据,包括JSON和文件编码。 (您可以添加Codable协议以同时使用编码和解码)

在Swift中使用JSON的常用解决scheme是使用字典。 所以你可以这样做:

 extension Date { var dataDictionary { return [ "year": self.year, "month": self.month, "day": self.day ]; } } extension Lad { var dataDictionary { return [ "firstName": self.firstName, "lastName": self.lastName, "dateOfBirth": self.dateOfBirth.dataDictionary ]; } } 

然后使用JSONSerialization序列化字典格式的数据。

 //someLad is a Lad object do { // encoding dictionary data to JSON let jsonData = try JSONSerialization.data(withJSONObject: someLad.dataDictionary, options: .prettyPrinted) // decoding JSON to Swift object let decoded = try JSONSerialization.jsonObject(with: jsonData, options: []) // after decoding, "decoded" is of type `Any?`, so it can't be used // we must check for nil and cast it to the right type if let dataFromJSON = decoded as? [String: Any] { // use dataFromJSON } } catch { // handle conversion errors } 

如果你只需要为几个类做这个,提供方法把它们变成字典是最可读的选项,不会让你的应用程序明显变大。

但是,如果您需要将许多不同的类转换为JSON,那么写出如何将每个类转换为字典是很繁琐的。 因此,使用某种reflectionAPI以便能够列出对象的属性将是有用的。 最稳定的select似乎是EVreflection 。 使用EVReflection,对于我们想要变成json的每个类,我们可以这样做:

 extension SomeClass: EVReflectable { } let someObject: SomeClass = SomeClass(); let someObjectDictionary = someObject.toDictionary(); 

然后,就像以前一样,我们可以使用JSONSerialization刚刚获得的字典序列化为JSON。 我们只需要使用object.toDictionary()而不是object.dataDictionary

如果您不想使用EVReflection ,则可以使用Mirror类实现reflection(可以查看对象具有哪些字段并遍历它们)。 这里有一个关于如何使用Mirror的解释。

所以,在定义了.dataDictionary计算variables或者使用EVReflection.toDictionary()方法之后,我们可以做

 class ApiService { func postDataToTheServer(lad: Lad) { //if using a custom method let dict = lad.dataDictionary //if using EVReflection let dict = lad.toDictionary() //now, we turn it into JSON do { let jsonData = try JSONSerialization.data(withJSONObject: dict, options: .prettyPrinted) // send jsonData to server } catch { // handle errors } } } 

可能这个GitHub代码将帮助你。

 protocol SwiftJsonMappable { func getDictionary() -> [String: Any] func JSONString() -> String } extension SwiftJsonMappable { //Convert the Swift dictionary to JSON String func JSONString() -> String { do { let jsonData = try JSONSerialization.data(withJSONObject: self.getDictionary(), options: .prettyPrinted) // here "jsonData" is the dictionary encoded in JSON data let jsonString = String(data: jsonData, encoding: .utf8) ?? "" // here "decoded" is of type `Any`, decoded from JSON data return jsonString // you can now cast it with the right type } catch { print(error.localizedDescription) } return "" } //Convert Swift object to Swift Dictionary func getDictionary() -> [String: Any] { var request : [String : Any] = [:] let mirror = Mirror(reflecting: self) for child in mirror.children { if let lable = child.label { //For Nil value found for any swift propery, that property should be skipped. if you wanna print nil on json, disable the below condition if !checkAnyContainsNil(object: child.value) { //Check whether is custom swift class if isCustomType(object: child.value) { //Checking whether its an array of custom objects if isArrayType(object: child.value) { if let objects = child.value as? [AMSwiftBase] { var decodeObjects : [[String:Any]] = [] for object in objects { //If its a custom object, nested conversion of swift object to Swift Dictionary decodeObjects.append(object.getDictionary()) } request[lable] = decodeObjects } }else { //Not an arry, and custom swift object, convert it to swift Dictionary request[lable] = (child.value as! AMSwiftBase).getDictionary() } }else { request[lable] = child.value } } } } return request } //Checking the swift object is swift base type or custom Swift object private func isCustomType(object : Any) -> Bool { let typeString = String(describing: type(of: object)) if typeString.contains("String") || typeString.contains("Double") || typeString.contains("Bool") { return false } return true } //checking array private func isArrayType(object : Any) -> Bool { let typeString = String(describing: type(of: object)) if typeString.contains("Array"){ return true } return false } //Checking nil object private func checkAnyContainsNil(object : Any) -> Bool { let value = "\(object)" if value == "nil" { return true } return false } } 

https://github.com/anumothuR/SwifttoJson