swift中字符串型数据映射为数值型数据的解决办法

一条json数据,全部是字符串类型的,如

{
      navi_radio = "2.10"
      price = "10"
      price_radio = "-0.28"
      ...
      diff = "--"  
}

这一条json实际上包含数值型的字符串传数据和以及真正的字符串,如果全在映射时全部转换为数值型(Double ,Int之类的),那么会有crash的情况,因为有些并不是数值型,而是真正的字符串,而且在全部设置为数值型的时候,映射出来的值也不对,全部为nil,因为数据类型不对,objectMapper映射的结构与后台返回的json数据结构是一致的,后台返回什么样的数据类型,就只能用什么样的数据类型字段解析,否则没有结果。我用的是realmSwift 进行存储,发现realmSwift对这种数值型字符串排序的支持并不好,存在排序不准确的情况(而且是一定会发生的情况),映射框架我用的是 objectMapper,在处理这个问题上,在realm-cocoa的issue上请教了作者,最后找到了解决办法
objectMapper提供了一种转换机制,在映射的时候就可以进行转换,


class Model: Object, Mappable {
  dynamic var navi_radio = ""       
  dynamic var price = "" 
  dynamic var price_radio = ""   
//   这里必须是对应的字符串类型,虽然知道它是数值型的,
//   如果强制转换为 dynamic var price = 0.00 这样的数据,结果为nil
  required convenience init?(_ map: Map) {
             self.init() 
       } 
   
func mapping(map: Map) { 
          navi_radio <- map["navi_radio"] 
          price <- map["price"] 
          price_radio <- map["price_radio"] 
          ...
          diff <- map["diff"] 
    }
}
// 这是基本的映射结构,如果仅仅是这样,是解决不了问题的.

那么就需要用下面的方法来进行转换了。

class Model: Object, Mappable {
  dynamic var navi_radio = ""       
  dynamic var price = "" 
  dynamic var price_radio = ""   
//   这里必须是对应的字符串类型,虽然知道它是数值型的,
//   如果强制转换为 dynamic var price = 0.00 这样的数据,结果为nil
  required convenience init?(_ map: Map) {
             self.init() 
       } 
   
// 将String转换为为Double型 - 进行映射
let transformDouble = TransformOf<Double, String>(fromJSON: { (value: String?) -> Double? in 
          // transform value from String? to Double? 
          return Double(value!)
}, toJSON: { (value: Double?) -> String? in 
          // transform value from Double? to String?
         if let value = value { 
                return String(value) 
          }
           return nil
      })

// 将String转换为Int进行映射
let transformInt = TransformOf<Int, String>(fromJSON: { (value: String?) -> Int? in 
          // transform value from String? to Int? 
          return Int(value!)
}, toJSON: { (value: Int?) -> String? in 
          // transform value from Int? to String?
         if let value = value { 
                return String(value) 
          }
           return nil
      })

// 映射结构
func mapping(map: Map) { 
          navi_radio <-(map["navi_radio"],transformDouble) 
          price <- (map["price"] ,transformInt)
          price_radio <- (map["price_radio"] ,transformDouble)
          ...
          diff <- map["diff"] 
    }
}

if let value = value { 
                return String(value) 
         }
           return nil
在这里原路返回就行,根据你的喜好返回对应的空值就OK了

映射时调用上面的转换方法,哪个字段需要转换,就用哪个字段调用对应的方法
此外,这个方法可以写多个,
比如现在这上面可以写Double型的转换,同时还可以写Int型的转换,等等...
至于diff = "--"这样的其实表示的没值的情况,返回的是 "--",那么遇到"--"这的情况下会走下面这句代码
转换为数值型后,排序就准确了。

推荐阅读更多精彩内容