swift JSON转Model 模型优化

2018-11-05  本文已影响0人  丢了理想

标准模型

struct Model:Codable {
    let id:Int
    let avatar:URL
    let nickname:String
    let publish:TimeInterval
}
//解析数据
        do {
           model = try JSONDecoder().decode(Model.self, from: data!)
        } catch  {
                print(error)
        }

//归档保存数据
            do {
                let data = try JSONEncoder().encode(model)
                try data.write(to: path, options: Data.WritingOptions.fileProtectionMask)
            } catch  {
                print(error)
            }
//解档
            do {
                let data = try Data.init(contentsOf: path)
                let model = try JSONDecoder().decode(Model.self, from: data!)
            } catch  {
                print(error)
            }



因为有时后台给的字段与客户端不匹配或者字段会变
如:nickname nickName
现在优化模型字段

struct Model:Codable {
    let id:Int
    let avatar:URL
    let nickname:String
    let publishTime:TimeInterval
    enum CodingKeys: String, CodingKey {
        case id, avatar, nickname, nickName
        case publishTime = "publish"
    }
    init(from decoder: Decoder) throws {
          let container = try decoder.container(keyedBy: CodingKeys.self)
          id = try container.decodeIfPresent(Int.self, forKey: .words)
          //其他的也要补齐
          nickname = try container.decodeIfPresent(String.self, forKey: .nickname)
          if nickname == nil{
          nickname = try container.decodeIfPresent(String.self, forKey: .niceName)
          }
    }
}

因为模型里是时间戳,如果需要转换为时间字符串
而且有的模型需要进行Array index索引,所以要继承Equatable协议

enum EnumType:String,Codable {
    case H5 = "H5"
    case APP = "APP"
}
struct Model:Codable,Equatable{
    let id:Int
    let avatar:URL
    let type: EnumType
    let nickname:String
    private let publishTime:TimeInterval//如果不使用可以私有
    var publishTimeString: String{
        get{
            let date = Date.init(timeIntervalSince1970: publishTime/1000)
            let formatter = DateFormatter()
            formatter.dateFormat = "MM-dd HH:mm"
            return formatter.string(from: date)
        }
    }
    enum CodingKeys: String, CodingKey {
        case id, avatar, nickname
        case publishTime = "publish"
    }
}

上面的代码有一个问题,如果产品更新,枚举类型变多了,不更新会报错
所以我们要重写 Codable协议

enum EnumType:String,Codable {
    case H5 = "H5"
    case APP = "APP"
    case `defult`
    init(from decoder: Decoder) throws {
          let container = try decoder.singleValueContainer()
          //这里只是一个样例,具体解析可以写的更完善
          self = EnumType(rawValue: try container.decode(String.self)) ?? . defult
    }
/***
    init(from decoder: Decoder) throws {
        do {
            let container = try decoder.singleValueContainer()
            let rawValue = try container.decode(String.self)
            self = EnumType(rawValue: rawValue) ?? . defult
        } catch  {
            throw error
        }
    }
***/
}
struct Model:Codable,Equatable{
    let id:Int
    let avatar:URL
    let type: EnumType
    let nickname:String
    private let publishTime:TimeInterval//如果不使用可以私有
    var publishTimeString: String{
        get{
            let date = Date.init(timeIntervalSince1970: publishTime/1000)
            let formatter = DateFormatter()
            formatter.dateFormat = "MM-dd HH:mm"
            return formatter.string(from: date)
        }
    }
    enum CodingKeys: String, CodingKey {
        case id, avatar, nickname, niceName//let不添加niceName
        case publishTime = "publish"
    }
    init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)
      id = try container.decodeIfPresent(Int.self, forKey: .words)
      //其他的也要补齐
      nickname = try container.decodeIfPresent(String.self, forKey: . nickname)
      if nickname == nil{
      nickname = try container.decodeIfPresent(String.self, forKey: . niceName)
      }
    }
}

使用经历
因为模型是一步一步优化过来的,所以尝试过其他方案
比如 lazy ,但是struct用lazy在使用的时候会报错,需要用muting func去实现,有一点麻烦
有的时候只需要修改一个数据名称,CodingKeys需要全部写,xcode没有自动生成

上一篇 下一篇

猜你喜欢

热点阅读