使用[String:Any]而不是NSDictionary的Swift3 JSONSerialization

时间:2016-12-09 13:47:32

标签: json swift

假设您有一个json someText字符串,并且您想将其解析为字典。以前我做过这个......

let jsonResult: NSDictionary =
   try JSONSerialization.jsonObject(
      with: someText.data(using: .utf8)!,
      options: JSONSerialization.ReadingOptions.mutableContainers)
         as! NSDictionary

但这只是一个糟糕的NSDictionary

看起来你确实可以这样做......

let jsonResult: [String:Any] =
   try JSONSerialization.jsonObject(
      with: someText.data(using: .utf8)!,
      options: JSONSerialization.ReadingOptions.mutableContainers)
         as! [String:Any]

所以现在它是一个真正的Swift词典。

这有用吗?是否存在激烈的效率差异,或者可能存在其他问题?

困惑地对我说,

  open class func jsonObject(with data: Data,
     options opt: JSONSerialization.ReadingOptions = []) throws -> Any

呼叫只会返回Any。因此,当您将其投放到[String:Any]NSDictionary时,过程是什么,最好的是什么?

2 个答案:

答案 0 :(得分:4)

  

是否存在激烈的效率差异

是的。

NSDictionary完全没有类型信息,本机Swift集合类型效率更高,强烈推荐。并且您使用var免费获得可变性。无论如何,mutableContainers在Swift中都是无用的。

jsonObject(with data返回Any,因为返回类型可以是DictionaryArray甚至是String/Number,最小公分母是Any,把它投射到预期的类型。

答案 1 :(得分:3)

在解析JSON对象时,{p> JSONSerialization.jsonObject(with:options:)会返回NSDictionary(如果是NSMutableDictionary,则返回.mutableContainers - 但这对于您的两个示例都是多余的)。

但是,由于根据解析的JSON数据类型可以返回其他类型,因此返回的静态类型为Any。因此,您需要将此结果转换为字典类型,以便通知编译器您正在解析的数据实际上是一个有效的JSON对象(当​​然,如果您不确定这一事实,那么,应该conditionally cast来处理它不是的情况。

当谈到Swift词典时,可以使用两种存储方案 - native或Cocoa。在将结果转换为[String : Any]的情况下,您使用Cocoa方案将NSDictionary桥接到Swift词典 - 这并不比只是底层NSDictionary的包装。

来自HashedCollections.swift.gyb

// Cocoa storage uses a data structure like this::
//
//   Dictionary<K,V> (a struct)
//   +----------------------------------------------+
//   | _VariantDictionaryBuffer<K,V> (an enum)     |
//   | +----------------------------------------+   |
//   | | [ _CocoaDictionaryBuffer (a struct) ] |   |
//   | +---|------------------------------------+   |
//   +-----|----------------------------------------+
//         |
//     +---+
//     |
//     V  NSDictionary (a class)
//   +--------------+
//   | [refcount#1] |
//   +--------------+

因此,就效率而言,在投射到NSDictionary[String : Any]之间没有真正的区别。无论如何,您仍然使用NSDictionary

但是,作为@vadian has already said,当在Swift中工作时,原生的Swift词典总是优先于普通NSDictionary,因为它们实际上携带有关其键的类型信息和值,编译器可以静态执行。