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

Problems with getting values out of nested dictionary in Swift 3 and Xcode 8

我用这个解析 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,所以我收到一个错误:

Type Any has no Subscript members

如何用 Xcode 8 修复它 Swift 3 ?我读过我可以转换它,但不知道如何使用我在 swift 3 中的嵌套字典和最新的 Xcode。我读过 但它对我的情况确实没有帮助。

问题是你没有指定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]
     }
}

您的 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? 转换。

所以,你可以一步一步来,在某些情况下 "need to" in 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。 )