将swift对象转换为JSON字符串

时间:2017-03-30 19:04:33

标签: ios json swift swift3

我有这样的课程:

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对象转换为JSON字符串,如下所示:

  

{       “名字”:“马尔可夫”       “姓氏”:“切尼”       “出生日期”:       {           “年”: “1901”,           “月”: “4”,           “天”: “30”       }   }

2 个答案:

答案 0 :(得分:4)

编辑 - 2017年10月31日:这个答案主要适用于Swift 3和可能的早期版本。截至2017年底,我们现在拥有Swift 4,您应该使用EncodableDecodable协议在表示之间转换数据,包括JSON和文件编码。 (您可以添加Codable协议以使用编码和解码)

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

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,那么写出如何将每个类转换为字典将会很繁琐。因此,使用某种反射API以便能够列出对象的属性会很有用。最稳定的选项似乎是EVReflection。使用EVReflection,对于我们想要变成json的每个类,我们可以这样做:

extension SomeClass: EVReflectable { }

let someObject: SomeClass = SomeClass();
let someObjectDictionary = someObject.toDictionary();

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

如果您不想使用EVReflection,则可以使用Mirror类自行实现反射(能够查看对象具有哪些字段并对其进行迭代)。有一个关于如何为此目的使用Mirror的解释here

因此,定义了.dataDictionary计算变量或使用EVReflection的{​​{1}}方法,我们可以做到

.toDictionary()

答案 1 :(得分:0)

愿这个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