如何将Swift对象转换为字典

时间:2015-08-12 16:58:04

标签: json swift dictionary service alamofire

我对iOS编程比较陌生。但是,我会假设Swift有一种将对象转换为JSON的自动方式,反之亦然。话虽这么说,我找到了几个可以做到这一点的库。

...无论其

似乎无论您如何将数据发布到Web服务(甚至使用类似AlamoFire之类的东西),请求必须是字典。所有这些论坛都展示了将返回的JSON字符串转换为对象是多么容易的示例。真正。但是请求需要手动编码。也就是说,遍历所有对象属性并将它们映射为字典。

所以我的问题是:我错过了什么吗?我是否完全错了,有一种超级简单的方法可以(a)在REQUEST中发送JSON(而不是字典)或(b)自动将对象转换为字典?

再次,我看到处理JSON响应是多么容易。我只是在寻找一种自动方式将我想要发布到Web服务的请求对象转换为像AlamoFire(或其他)这样的库所需的格式。使用其他语言这是相当微不足道的,所以我希望Swift可以采用同样简单易用的方式。

4 个答案:

答案 0 :(得分:8)

Swift目前不支持像Java或C#这样的高级反射,所以答案是:不,纯粹的Swift没有同样简单易用的方法。

[更新] Swift 4同时具有Codable协议,允许序列化到/来自JSON和PLIST。

typealias Codable = Decodable & Encodable

答案 1 :(得分:5)

不使用反射,适用于嵌套对象(Swift 4):

protocol Serializable {
    var properties:Array<String> { get }
    func valueForKey(key: String) -> Any?
    func toDictionary() -> [String:Any]
}

extension Serializable {
    func toDictionary() -> [String:Any] {
        var dict:[String:Any] = [:]

        for prop in self.properties {
            if let val = self.valueForKey(key: prop) as? String {
                dict[prop] = val
            } else if let val = self.valueForKey(key: prop) as? Int {
                dict[prop] = val
            } else if let val = self.valueForKey(key: prop) as? Double {
                dict[prop] = val
            } else if let val = self.valueForKey(key: prop) as? Array<String> {
                dict[prop] = val
            } else if let val = self.valueForKey(key: prop) as? Serializable {
                dict[prop] = val.toDictionary()
            } else if let val = self.valueForKey(key: prop) as? Array<Serializable> {
                var arr = Array<[String:Any]>()

                for item in (val as Array<Serializable>) {
                    arr.append(item.toDictionary())
                }

                dict[prop] = arr
            }
        }

        return dict
    }
}

只需为要转换的自定义对象实现属性和valueForKey。例如:

class Question {
    let title:String
    let answer:Int

    init(title:String, answer:Int) {
        self.title = title
        self.answer = answer
    }
}
extension Question : Serializable {
    var properties: Array<String> {
        return ["title", "answer"]
    }

    func valueForKey(key: String) -> Any? {
        switch key {
        case "title":
            return title
        case "answer":
            return answer
        default:
            return nil
        }
    }
} 

如果需要,可以在toDictionary函数中添加更多值类型。

答案 2 :(得分:3)

您还可以使用ObjectMapper库。它有一个&#34; toJSON&#34;将对象转换为字典的方法。

答案 3 :(得分:1)

我对此的解决方案将是这样的:

extension Encodable {

    var dict : [String: Any]? {
        guard let data = try? JSONEncoder().encode(self) else { return nil }
        guard let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String:Any] else { return nil }
        return json
    }
}

用法将是这样的:

movies.compactMap { $0.dict }