Swift版YYModel数据解析

103 阅读3分钟

之前一直是使用oc开发项目,最近新项目打算用Swift开发,不得不说Swift确实优秀,第一感受是不用处理.h和.m,只需要在Swift里面开发,大大的折叠了文件数量减半;由于是新手,但是在开发过程中还是不可避免的遇到了一些问题,比如我在oc中和后台对接中,请求数据和解析我一般都是用AFNetworking和YYModel,但是当我在Swift中想要使用YYModel来解析JSON数据并保存模型的时候傻眼了,不能使用,Swift的模型概念不一样,然后我就查资料,网上推荐了很多第三方解析框架,但我挨个试了下都不是很喜欢(包括Swift自带的),总感觉太繁琐,而且我们后端接口有很多不规范的地方,比如isVip、id之类的,有时候他返回的是double类型,有时候又是bool类型,在我定义模型变量类型的时候很难受,经常出现测试没问题,上线出问题,某个value解析不出来导致App异常,后来我慢慢研究了下做出了我的解决方案,我不管你给的是什么类型,我定义了什么类型,就自动强转为什么类型,经测试很好用,我不知道大佬有没有别的高招,但是对于一个初学者和自行摸索者,我把我的想法分享出来,欢迎点评与提建议。(废话完成)

使用框架如下:

Pods:
pod 'ObjectMapper'
pod 'Alamofire'

然后创建一个AllModelManagers.Swift(举例),在里面粘贴如下代码:

**import** ObjectMapper

  


// **MARK: 定义一个通用的 ForceConvertType 泛型转换器******

**struct** ForceConvertType<T>: TransformType {

    **func** transformFromJSON(_ value: **Any**?) -> T? {

        **guard** **let** value = value **else** { **return** **nil** }

  


        // 直接尝试强制转换为目标类型

        **if** **let** typedValue = value **as**? T {

            **return** typedValue

        }

  


        // 类型不匹配时,尝试其他类型转换

        **if** T.**self** == Int.**self**, **let** stringValue = value **as**? String, **let** intValue = Int(stringValue) {

            **return** intValue **as**? T

        } **else** **if** T.**self** == String.**self**, **let** intValue = value **as**? Int {

            **return** String(intValue) **as**? T

        } **else** **if** T.**self** == Double.**self**, **let** stringValue = value **as**? String, **let** doubleValue = Double(stringValue) {

            **return** doubleValue **as**? T

        } **else** **if** T.**self** == Float.**self**, **let** stringValue = value **as**? String, **let** floatValue = Float(stringValue) {

            **return** floatValue **as**? T

        } **else** **if** T.**self** == Bool.**self**, **let** intValue = value **as**? Int {

            **return** (intValue != 0) **as**? T

        } **else** **if** T.**self** == Bool.**self**, **let** stringValue = value **as**? String {

            **let** lowercasedValue = stringValue.lowercased()

            **return** (lowercasedValue == "true" || lowercasedValue == "1") **as**? T

        } **else** **if** T.**self** == [String].**self**, **let** stringArray = value **as**? [String] {

            **return** stringArray **as**? T

        } **else** **if** T.**self** == [String: **Any**].**self**, **let** dictionary = value **as**? [String: **Any**] {

            **return** dictionary **as**? T

        } **else** **if** T.**self** == Date.**self**, **let** stringValue = value **as**? String {

            // 支持日期格式解析,尝试多种格式

            **let** dateFormats = ["yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy/MM/dd", "MM/dd/yyyy"]

            **let** dateFormatter = DateFormatter()

            **for** format **in** dateFormats {

                dateFormatter.dateFormat = format

                **if** **let** date = dateFormatter.date(from: stringValue) {

                    **return** date **as**? T

                }

            }

        }

  


        // 处理失败,返回 nil

        **return** **nil******

    }

  


    **func** transformToJSON(_ value: T?) -> **Any**? {

        **if** **let** value = value {

            // 转换回 JSON 格式时,处理特定类型

            **if** T.**self** == Date.**self**, **let** date = value **as**? Date {

                **let** dateFormatter = DateFormatter()

                dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss" // 统一日期格式

                **return** dateFormatter.string(from: date)

            }

        }

        **return** value

    }

}

然后只需要在创建模型的时候如下在mapping方法里面追加ForceConvertType(),即可后患无忧了,再出问题前端就不背锅:

**struct** TestModel: Mappable {

    

    var ageValue: Int = 0
    var isVip: Bool = false
    var avatar: String = ""
    var imageList: [string] = []

    **init**?(map: Map) { }

    **mutating** **func** mapping(map: Map) {
    
        ageValue <- (map["age"], ForceConvertType())
        isVip <- (map["isVip"], ForceConvertType())
        avatar <- (map["avatar"], ForceConvertType())
        imageList <- (map["imageList"], ForceConvertType())

    }

}