在 Swift 3 和 Xcode 8 中从嵌套字典中获取值的问题

Posted

技术标签:

【中文标题】在 Swift 3 和 Xcode 8 中从嵌套字典中获取值的问题【英文标题】:Problems with getting values out of nested dictionary in Swift 3 and Xcode 8 【发布时间】:2016-09-08 13:45:02 【问题描述】:

我用这个解析 JSON:

 let dictionary = try JSONSerialization.jsonObject(with: geocodingResultsData as Data, options: .mutableContainers)

并得到以下嵌套字典作为结果

 response =   GeoObjectCollection =  featureMember =  
( 
  GeoObject =  Point =   pos = "40.275713 59.943413"; ;   ;  ,
  GeoObject =  Point =   pos = "40.273162 59.944292"; ;  ;   
);
;
;

我正在尝试从该字典中获取坐标值并将它们保存到新的 latutudeString 和 longitudeString 变量中

在 Xcode 8 GM 之前,它使用此代码为我工作:

 if let jsonCoordinatesString: String = dictionary["response"]!!["GeoObjectCollection"]!!["featureMember"]!![0]["GeoObject"]!!["Point"]!!["pos"]!! as? String 

            var latLongArray = jsonCoordinatesString.components(separatedBy: " ")

            let latitudeString = latLongArray[1]
            let longitudeString = latLongArray[0]

        

但由于我安装了 Xcode 8 GM,我收到一个错误:

Any 类型没有下标成员

如何用 Xcode 8 修复它 Swift 3 ?我读过我可以转换它,但不知道如何让它与我在 swift 3 中的嵌套字典和最新的 Xcode 一起工作。我读过can't resolve "Ambiguous use of subscript",但对我来说确实没有帮助。

【问题讨论】:

can't resolve "Ambiguous use of subscript"的可能重复 我已经检查了主题@Larme,但它对我的情况没有帮助,所以仍然不知道如何在 Swift 3 / Xcode 8 中解决我的问题。如果我将字典转换为 [ AnyObject],我仍然收到类型 [AnyObject] 没有下标成员的错误。 【参考方案1】:

您的 JSON 数据在 Swift 中具有这种类型:

[String: [String: [String: [[String: [String: [String: String]]]]]]]

我会避免使用这种嵌套太深的类型,但如果你敢使用,你可以写这样的东西:

enum MyError: Error 
    case invalidStructure

do 
    guard let dictionary = try JSONSerialization.jsonObject(with: geocodingResultsData as Data, options: .mutableContainers) as? [String: [String: [String: [[String: [String: [String: String]]]]]]] else 
        throw MyError.invalidStructure
    
    if let jsonCoordinatesString: String = dictionary["response"]?["GeoObjectCollection"]?["featureMember"]?[0]["GeoObject"]?["Point"]?["pos"] 

        var latLongArray = jsonCoordinatesString.components(separatedBy: " ")

        let latitudeString = latLongArray[1]
        let longitudeString = latLongArray[0]

    
 catch let error 
    print(error)

但您可能隐藏了一些不相关的 JSON 数据成员,这可能会破坏 as? 转换。

所以,你可以一步一步来,在某些情况下“需要”在 Swift 3 中,像这样:

do 
    guard let dictionary = try JSONSerialization.jsonObject(with: geocodingResultsData as Data, options: .mutableContainers) as? [String: AnyObject] else 
        throw MyError.invalidStructure
    
    if
        let response = dictionary["response"] as? [String: AnyObject],
        let geoObjectCollection = response["GeoObjectCollection"] as? [String: AnyObject],
        let featureMember = geoObjectCollection["featureMember"] as? [[String: AnyObject]],
        !featureMember.isEmpty,
        let geoObject = featureMember[0]["GeoObject"] as? [String: AnyObject],
        let point = geoObject["Point"] as? [String: AnyObject],
        let jsonCoordinatesString = point["pos"] as? String
    
        var latLongArray = jsonCoordinatesString.components(separatedBy: " ")

        let latitudeString = latLongArray[1]
        let longitudeString = latLongArray[0]

    
 catch let error 
    print(error)

lets 对于 Swift 3 中的每个可选绑定都是必需的。如果您愿意,可以将所有 AnyObjects 更改为 Anys。)

【讨论】:

【参考方案2】:

问题是你没有指定dictionary对象的类型,你需要像这样显式指定dictionary对象的类型为Dictionary

let dictionary = try JSONSerialization.jsonObject(with: geocodingResultsData as Data, options: .mutableContainers) as! [String: Any]

if let response = dictionary["response"] as? [String: Any], 
   let geoObjectCollection = response["GeoObjectCollection"] as? [String: Any],
   let featureMember = geoObjectCollection["featureMember"] as? [[String: Any]] 

     if let geoObject = featureMember[0]["GeoObject"] as? [String: Any],
        let point = geoObject["Point"] as? [String: String] 
            let latLongArray = point["pos"].components(separatedBy: " ")
            let latitudeString = latLongArray[1]
            let longitudeString = latLongArray[0]
     

【讨论】:

我尝试这样做但仍然收到类型“Any”没有下标成员,我尝试让字典 = 尝试 JSONSerialization.jsonObject(with: geocodingResultsData as Data, options: .mutableContainers) as! [String: Any] 并让 dictionary = try JSONSerialization.jsonObject(with: geocodingResultsData as Data, options: .mutableContainers) as! [String: AnyObject] 但在这两种情况下获取类型“任何”都没有下标琥珀

以上是关于在 Swift 3 和 Xcode 8 中从嵌套字典中获取值的问题的主要内容,如果未能解决你的问题,请参考以下文章

无法在 Xcode 控制台中从 Objective-C 记录 Swift Singletons

在 XCode 6 beta 7 中从 Swift 在 iOS 中打印

如何在 xcode (swift) 中从 Json Schema / Json 生成模型对象?

如何在 swift 4.1 和 xcode 9.3 中使用 JSONDecoder 解码嵌套的 JSON 数组和对象?

在 Swift 的嵌套循环中从特定索引枚举字符串

自 Xcode 12 (Swift 5.3) 以来,嵌套集合视图不响应单元格选择