首页 文章

将swift对象转换为JSON字符串

提问于
浏览
2

我有这样的课程:

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字符串,如下所示:

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

2 回答

  • 0

    编辑 - 10/31/2017:这个答案主要适用于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类自己实现反射(能够查看对象具有哪些字段并迭代它们) . 有一个解释如何为此目的使用镜像here .

    因此,定义了 .dataDictionary 计算变量或使用 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
        }
      }
    }
    
  • 4

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

相关问题