Codable实现json转Model,是时候干掉HandyJSON了!

内容预览:

    自从开始使用Swift做项目,一直都在使用HandyJSON,不可否认,HandyJSON在Swift4.0是个好东西,也尝试过其它json转mode的工具,最终发现还是HandyJSON最好用. 去年Swift4.0发布之后,一个最有趣的变化就是Codable协议. 一直都知道Codable来实现json转model,不但效率高,并且简单易用, 但是一直拖到最近才简单封装个小工具,为什么呢? ?!!!

    在工具的封装上,参考了HandyJSON的部分代码,在使用HandyJSON过程中,一直都觉得designatedPath是一个很牛逼的存在,开发效率提升了不是一个量级,于是这里也参考HandyJSON中designatedPath的实现代码,并根据Codable的需要改造成fileprivate func getInnerObject(inside jsonData: Data?, by designatedPath: String?) -> Data?方法. 在这里感谢HandyJSON开发组.

    Codable工具CodableHelper全部代码如下所示.100余行的代码前后花费一天多的时间. 当了解到google工程师日均一百多行的代码量,我觉得这速度还可以吧. 在代码质量和阅读质量上不敢说有多好,我只是按照自己认为最好的方式来做,如果有哪里不当或者可以用更好方法解决的地方,烦请各位告知,彼此交流学习.

    CodableHelper实现代码如下所示:

    import Foundation

    /// 扩展Codable协议,提供更便捷的编码解码方法
    public protocol CodableHelper: Codable { }

    public extension CodableHelper {

    //1.遵守CodableHelper协议的对象转json字符串
    public func toJSONString() -> String? {
    guard let data = try? JSONEncoder().encode(self) else {
    return nil
    }
    return String(data: data, encoding: .utf8)
    }

    //2.对象转换成jsonObject
    public func toJSONObject() -> Any? {
    guard let data = try? JSONEncoder().encode(self) else {
    return nil
    }
    return try? JSONSerialization.jsonObject(with: data, options: .allowFragments)
    }

    //3.json字符串转对象
    public static func decodeJSON(from string: String?, designatedPath: String? = nil) -> Self? {

    guard let data = string?.data(using: .utf8),
    let jsonData = getInnerObject(inside: data, by: designatedPath) else {
    return nil
    }
    return try? JSONDecoder().decode(Self.self, from: jsonData)
    }

    //4.jsonObject转换对象或者数组
    public static func decodeJSON(from jsonObject: Any?, designatedPath: String? = nil) -> Self? {

    guard let jsonObject = jsonObject,
    JSONSerialization.isValidJSONObject(jsonObject),
    let data = try? JSONSerialization.data(withJSONObject: jsonObject, options: []),
    let jsonData = getInnerObject(inside: data, by: designatedPath) else {
    return nil
    }
    return try? JSONDecoder().decode(Self.self, from: jsonData)
    }
    }


    public extension Array where Element: CodableHelper {

    public static func decodeJSON(from jsonString: String?, designatedPath: String? = nil) -> [Element?]? {
    guard let data = jsonString?.data(using: .utf8),
    let jsonData = getInnerObject(inside: data, by: designatedPath),
    let jsonObject = try? JSONSerialization.jsonObject(with: jsonData, options: .allowFragments) as? [Any] else {
    return nil
    }
    return Array.decodeJSON(from: jsonObject)
    }

    public static func decodeJSON(from array: [Any]?) -> [Element?]? {
    return array?.map({ (item) -> Element? in
    return Element.decodeJSON(from: item)
    })
    }
    }


    /// 借鉴HandyJSON中方法,根据designatedPath获取object中数据
    ///
    /// - Parameters:
    /// - jsonData: json data
    /// - designatedPath: 获取json object中指定路径
    /// - Returns: 可能是json object
    fileprivate func getInnerObject(inside jsonData: Data?, by designatedPath: String?) -> Data? {

    //保证jsonData不为空,designatedPath有效
    guard let _jsonData = jsonData,
    let paths = designatedPath?.components(separatedBy: "."),
    paths.count > 0 else {
    return jsonData
    }
    //从jsonObject中取出designatedPath指定的jsonObject
    let jsonObject = try? JSONSerialization.jsonObject(with: _jsonData, options: .allowFragments)
    var result: Any? = jsonObject
    var abort = false
    var next = jsonObject as? [String: Any]
    paths.forEach({ (seg) in
    if seg.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) == "" || abort {
    return
    }
    if let _next = next?[seg] {
    result = _next
    next = _next as? [String: Any]
    } else {
    abort = true
    }
    })
    //判断条件保证返回正确结果,保证没有流产,保证jsonObject转换成了Data类型
    guard abort == false,
    let resultJsonObject = result,
    let data = try? JSONSerialization.data(withJSONObject: resultJsonObject, options: []) else {
    return nil
    }
    return data
    }

    CodableHelper工具的使用也是非常简单的,代码如下所示:

    //首先定义一个结构体Person用来表示数据Model
    struct Person: CodableHelper {
    var name: String?
    var age: Int?
    var sex: String?
    }


    //1.jsonString中获取数据封装成Model
    let p1String = "{"name":"walden","age":30,"sex":"man"}"
    let p1 = Person.decodeJSON(from: p1String)

    //2.jsonString中获取数据封装成Array
    let personString = "{"haha":[{"name":"walden","age":30,"sex":"man"},{"name":"healer","age":20,"sex":"female"}]}"
    let persons = [Person].decodeJSON(from: personString, designatedPath: "haha")

    //3.对象转jsonString
    let jsonString = p1?.toJSONString()

    //4.对象转jsonObject
    let jsonObject = p1?.toJSONObject()

    • 转载请注明出处

    以上就是:Codable实现json转Model,是时候干掉HandyJSON了! 的全部内容。

    本站部分内容来源于互联网和用户投稿,如有侵权请联系我们删除,谢谢。
    Email:[email protected]


    0 条回复 A 作者 M 管理员
      所有的伟大,都源于一个勇敢的开始!
    欢迎您,新朋友,感谢参与互动!欢迎您 {{author}},您在本站有{{commentsCount}}条评论