【问题标题】:Is there a better way to get numbers from dictionary (JSON data)?有没有更好的方法从字典(JSON 数据)中获取数字?
【发布时间】:2018-05-15 10:29:25
【问题描述】:

假设我收到一些 JSON 格式的数据,然后使用本机工具将其解析为字典。其中一些值是数字,我自然需要解析它们,将它们转换为我在应用程序中需要的值。

但是从AnyFloatIntDouble 等实际数字的转换似乎有点混乱。例如,如果我期望一个双精度,但在某些时候服务器返回一个整数,我的代码将失败使用:

let doubleValue = dictionary["key"] as! Double

因此,当项目为 1.3 时这将起作用,但对于 1 将失败。要使用更具体的示例,我们可以使用以下内容:

let myDictionary: [String: Any] = [
    "myNumber_int" : 1,
    "myNumber_float" : Float(1),
    "myNumber_cgFloat" : CGFloat(1),
    "myNumber_double" : 1.0
]

let numberInt1 = myDictionary["myNumber_int"] as? Int // 1
let numberInt2 = myDictionary["myNumber_int"] as? Float // nil
let numberInt3 = myDictionary["myNumber_int"] as? CGFloat // nil
let numberInt4 = myDictionary["myNumber_int"] as? Double // nil

let numberFloat1 = myDictionary["myNumber_float"] as? Int // nil
let numberFloat2 = myDictionary["myNumber_float"] as? Float // 1
let numberFloat3 = myDictionary["myNumber_float"] as? CGFloat // nil
let numberFloat4 = myDictionary["myNumber_float"] as? Double // nil

let numberCGFloat1 = myDictionary["myNumber_cgFloat"] as? Int // nil
let numberCGFloat2 = myDictionary["myNumber_cgFloat"] as? Float // nil
let numberCGFloat3 = myDictionary["myNumber_cgFloat"] as? CGFloat // 1
let numberCGFloat4 = myDictionary["myNumber_cgFloat"] as? Double // nil

let numberDouble1 = myDictionary["myNumber_double"] as? Int // nil
let numberDouble2 = myDictionary["myNumber_double"] as? Float // nil
let numberDouble3 = myDictionary["myNumber_double"] as? CGFloat // nil
let numberDouble4 = myDictionary["myNumber_double"] as? Double // 1

因此,对于每种类型,实际上只有 1 个演员可以工作,这是……好吧,我至少希望 CGFloat 能够直接转换为 DoubleFloat……

所以我的解决方案是使用NSNumber:

let myNumbers: [CGFloat] = [
    CGFloat((myDictionary["myNumber_int"] as? NSNumber)?.floatValue ?? 0.0),
    CGFloat((myDictionary["myNumber_float"] as? NSNumber)?.floatValue ?? 0.0),
    CGFloat((myDictionary["myNumber_cgFloat"] as? NSNumber)?.floatValue ?? 0.0),
    CGFloat((myDictionary["myNumber_double"] as? NSNumber)?.floatValue ?? 0.0),
] // [1,1,1,1]

这自然可行,但是对于像这样简单的事情,代码非常难看。但是把代码“丑陋”放在一边;如果不使用 Next Step,我们可以不做类似的事情吗?我的意思是NSNumber 像这样看似微不足道的事情?我在这里遗漏了一些非常明显的东西,对吧?

【问题讨论】:

  • 您是否必须“使用本机工具”解析 JSON?你不能用JSONDecoderCodable吗?
  • 当你从某处得到JSON时,整数值为Int,流动点值为Double,句号。如果您的解析器创建更多类型,请使用更好的解析器或考虑 Sweeper 的建议。
  • @vadian 如果 JSON 让您感到困惑,我深表歉意,但这只是一个例子。但即使只有整数和浮点数,问题仍然存在。
  • 如果您创建具有具体类型的字典,即使您将字典声明为[String:Any],这些类型仍然存在。同样,接收到的 JSON 只有两种类型。你甚至可以将1 转换为Double(当然反之亦然)。
  • 那么你应该在Swift 语言中使用AnyAny 用于非对象或Swift 中的所有类型,因此IntDoubleFloatArrayDictionary 这些都不是对象。 AnyObject 用于 Class 实例。一个问题,如果您不知道值的类型,那么您为什么要铸造。只有let numberInt2 = myDictionary["myNumber_int"] 肯定会起作用。

标签: swift dictionary casting


【解决方案1】:

试试这样:-

if let data = myDictionary as? [String: AnyObject] {
    let myNumber = data["myNumber_int"] as? Int
}

【讨论】:

  • 有趣。显然没有机会转换整个字典,但以下确实有效:(myDictionary["myNumber_int"] as? AnyObject) as? Float.
  • 它仍然很丑陋,如果我错了,请纠正我,但 AnyObject 不是为 ObjectiveC 桥设计的吗?
  • 如果字典没有值,它也会帮助你处理零值...如果你有字典数组,那么创建模型来获取结构数据
  • 它确实有效,我只是在操场上测试了它。我只是不完全理解为什么......在这种情况下,Any 和 AnyObject 之间的主要区别是什么
  • 我想我知道发生了什么...通过这样做,您可以连接到 ObjectiveC,它现在会自动将所有原语转换为 NSNumber。现在NSNumber 可以自动转换为 Swift 中的任何原语。我在初始字典中使用"myNumber_int" : NSNumber(value: 1.0) 对此进行了测试,第一部分所有返回值(全部正确转换)。因此,在这种情况下,基本上第一次演员表是自动为我们完成的,仅此而已。但如果可能的话,我想避免使用 ObjectiveC 和 NSNumber
猜你喜欢
  • 1970-01-01
  • 2011-10-05
  • 1970-01-01
  • 1970-01-01
  • 2018-09-08
  • 2010-11-11
  • 2021-05-31
  • 1970-01-01
相关资源
最近更新 更多