分享

iOS学习心得--ObjectMapper数据转换解析

 昵称v8JFa 2016-10-12

最近学习了ObjectMapper,于是将自己的学习心得记录下来。这个库的使用本身就很简单方便,很快就能上手。并且ObjectMapper 的 github上的文档已经把该库的使用讲得很详细了,如果有英文基础的还是建议直接看官方文档,如果还有不懂的地方可以看看这篇文章中我的理解,希望能给您带来帮助。

NSJSONSerialization类让JSON解析变得非常简单,然而第三方的objectMapper能让JSON数据直接变成对象,这就让我在开发中能够更好使用和管理数据。

ObjectMapper学起来非常简单,而且将数据转换成对象的好处就不用多说了。

基本语法

使用之前首先要pod,这个不用多说了

pod 'ObjectMapper'
use_frameworks!

我自己的demo数据接口是实用的天气预报的数据接口,以下用我自己的domo举例
JSON例子:

{
    errNum: 0,
    errMsg: "success",
    retData: {
        city: "北京",  //城市名称
        cityid: "101010100", //城市编码
        today: {
            date: "2015-08-03", //今天日期
            week: "星期一",    //今日星期
            curTemp: "28℃",    //当前温度
            aqi: "92",        //pm值
            fengxiang: "无持续风向", //风向
            fengli: "微风级",     //风力
            hightemp: "30℃",   //最高温度
            lowtemp: "23℃",    //最低温度
            type: "阵雨",      //天气状态   
            index: [  //指标列表
                {
                    name: "感冒指数", //指数指标1名称
                    code: "gm",     //指标编码  
                    index: "",      //等级
                    details: "各项气象条件适宜,发生感冒机率较低。但请避免长期处于空调房间中,以防感冒。",//描述
                    otherName: "" //其它信息
                },
               ......
            ]
        },
        forecast: [ //回来预报列表
            {
                date: "2015-08-04",
                week: "星期二",
                fengxiang: "无持续风向",
                fengli: "微风级",
                hightemp: "32℃",
                lowtemp: "23℃",
                type: "多云"
            },
           ......
        ],
        history: [ //历史天气列表

            {
                date: "2015-07-31",
                week: "星期五",
                aqi: "52",
                fengxiang: "无持续风向",
                fengli: "微风级",
                hightemp: "高温 29℃",
                lowtemp: "低温 22℃",
                type: "多云"
            },
            ......
        ]
    }
}

首先是建立数据对应的类,遵循Mappable协议,并且实现两个协议方法。比较好的做法是先建立一个基类,遵循Mappable协议,再让其他类继承自基类。这样在面对多个接口的时候可以添加一些公共的属性。

import ObjectMapper
class BaseData: NSObject , Mappable{
    required init?(_ map: Map) {

    }
    func mapping(map: Map) {

    }
}

demo中是直接拿‘retData’中的数据,所以数据类直接对应请求结果中'retData'的值

只需要在数据类中声明对应的属性,并且在协议方法mapping(_:)中实现:

‘属性名 <- map["key名称"]’,即可

import ObjectMapper
class WeatherData: BaseData{
    var city : String?
    var cityid : String?
    var forecast : [ForecastData]?
    var history : [HistoryData]?
    var todayWeather : TodayWeatherData?

    override func mapping(map: Map) {
        city <- map["city"]
        cityid <- map["cityid"]
        forecast <- map["forecast"]
        history <- map["history"]
        todayWeather <- map["today"]
    }
}

多层数据,只需实现对应的数据类即可,比如‘var history : [HistoryData]?’,实现对应的HistoryData类,就可以自动解析返回结果中数组中的内容,并且关联到history属性上。

class BaseADayWeather: BaseData {
    var date : NSDate?
    var hightTemp : Int?
    var lowTemp : Int?
    var type : String?
    var week : String?

    override func mapping(map: Map) {
        date <- (map["date"] , transfromOfDateAndString())
        hightTemp <- (map["hightemp"] ,transfromOfIntAndString())
        lowTemp <- (map["lowtemp"] ,transfromOfIntAndString())
        type <- map["type"]
        week <- map["week"]
    }
}

class HistoryData: BaseADayWeather {

}

数据转换

可以看到上面有这样的代码‘date <- (map["date"] , transfromOfDateAndString())’
这里就涉及到了数据转换。objectMapper本身只支持一部分数据类型的转换:

  • Int
  • Bool
  • Double
  • Float
  • String
  • RawRepresentable (Enums)
  • Array<AnyObject>
  • Dictionary<String, AnyObject>
  • Object<T: Mappable>
  • Array<T: Mappable>
  • Array<Array<T: Mappable>>
  • Set<T: Mappable>
  • Dictionary<String, T: Mappable>
  • Dictionary<String, Array<T: Mappable>>
  • Optionals of all the above
  • Implicitly Unwrapped Optionals of the above

如果你的数据是NSDate呢?或者你的数据字符串格式与需求不符呢?就需要用到mapper的转换。
mapper给出了一个官方的转换对象 DateTransform()

birthday <- (map["birthday"], DateTransform()),这句代码可以将birthday对应的int转换成NSDate,但是好像官方只给了这一个。。。需要其它转换方式就必须要自己写。

这里就需要用到TransformOf类 。

id <- (map["id"], TransformOf<Int, String>(fromJSON: { Int($0!) }, toJSON: { $0.map { String($0) } }))

官方给出的例子,简单粗暴地将int和string进行转换。当然,更优雅的写法就是像DateTransform()一样。写一个函数,返回一个TransformOf。

import ObjectMapper
//返回的温度数据是string 例如“26℃”,我不需要“℃”,我只需要int,就可以写如下的转换
func transfromOfIntAndString() -> TransformOf<Int , String>{
    return TransformOf<Int , String>.init(fromJSON: { (JSONString) -> Int? in
        if var str = JSONString{
            str = str.substringToIndex(str.endIndex.advancedBy(-1))
            return Int(str)
        }
        return nil
        }, toJSON: {String($0!)}) //这里偷了个懒。。。。
}

func formatter() -> NSDateFormatter{
    let formatter = NSDateFormatter()
    formatter.dateFormat = "yyyy-MM-dd"
    return formatter
}
//将"yyyy-MM-dd"格式的string转成date
func transfromOfDateAndString() ->TransformOf<NSDate , String>{
    return TransformOf<NSDate , String>.init(fromJSON: { (JSONString) -> NSDate? in
            if let str = JSONString{
                return formatter().dateFromString(str)
            }
            return nil
        }, toJSON: { (date) -> String? in
            if let date = date{
                return formatter().stringFromDate(date)
            }
            return nil
    })
}

class BaseADayWeather: BaseData {
    var date : NSDate?
    var hightTemp : Int?
    var lowTemp : Int?
    var type : String?
    var week : String?

    override func mapping(map: Map) {
        date <- (map["date"] , transfromOfDateAndString()) //调用转换函数,
        hightTemp <- (map["hightemp"] ,transfromOfIntAndString())
        lowTemp <- (map["lowtemp"] ,transfromOfIntAndString())
        type <- map["type"]
        week <- map["week"]
    }
}

写完后感觉真的很简单。。。自己废话很多。。

最后附上demo地址:LearnObjectMapper - MangoMade

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多