如何从不同级别的JSON对象中提取数据

时间:2018-04-21 22:34:33

标签: ios json swift xcode api

所以我有一个看起来像这样的json对象。

{
        geometry =     {
            location =         {
                lat = "51.5194133";
                lng = "-0.1269566";
            };
        };
        id = ad6aaec7b7b0fa2c97a127c24845d76135e760ae;
        "place_id" = ChIJB9OTMDIbdkgRp0JWbQGZsS8;
        reference = "CmRRAAAAiC-ErdlAvz74Drejj2mAAh6Plr46e889a3Uv6CrRXFqNtVatoFsOTarDH0KU8KCkWoN--QGv01RSjLBZblbrAHNPGDVdiXikedid0vKMVM_LQtXstrSQFt4s-Z-Wi-1AEhDJRWc9bdWpKHPPOrt7QGTqGhSJgMPENn_wSGbprGYLv52csv5BtQ";
    }

我想知道如何在不同级别提取信息,例如,位置对象是几何对象中的对象,我想从那里提取lat,我该怎么做?

我可以打印出位置对象,如:

let setOne = jsonResult["results"]! as! NSArray
            let y = setOne[0] as? [String: AnyObject]
            print(y!)
            print((y!["geometry"]!["location"]!)!["lat"])

但是当我尝试做的时候:

print((y!["geometry"]!["location"]!)!["lat"])

它给了我错误:输入'Any'没有下标成员

3 个答案:

答案 0 :(得分:2)

也许最简单的方法是使用JSONDecoder将JSON直接解码为结构。

首先需要定义与JSON结构匹配的结构,如下所示:

struct Place: Codable {
    let geometry: Geometry
    let id: String
    let place_id: String
    let reference: String
}
struct Geometry: Codable {
    let location: Location
}
struct Location: Codable {
    let lat: String
    let lng: String
}

现在,假设jsonResult["results"]实际上是NSArray,您首先需要将其转换为Data,然后使用JSONDecoder将JSON解码为结构:

if let data = try? JSONSerialization.data(withJSONObject: jsonResult["results"], options: []) {
    if let places = try? JSONDecoder().decode(Array<Place>.self, from: data) {
        print(places[0].geometry.location.lat) //prints "51.5194133"
    }
}

这种方法的优点是您可以编写更少的代码来进行实际解码。

请注意,如果可能缺少任何JSON元素,则应将相应的struct let属性声明为可选。例如,如果reference可能并不总是存在,则将其编码为:

let reference: String?

任何非可选的东西都必须存在于JSON中,否则解码将失败。这就是您希望在解码时使用try?的原因,以便您的应用不会崩溃。

答案 1 :(得分:0)

假设你有一系列结果数据,你不需要使用NSArray,因为你使用的是Swift,所以你可以在这里开始。

在Swift中你需要指定类型,并且除非你真的需要它,否则尽量不要使用AnyObject,总是提供类型,这就是错误所说的内容:

// make sure that results exist 
if let resultArray = jsonResult["results"] as? [Dictionary<String,Any>] {
 // loop through the result array
 for object in resultArray {
   // get geometry from the object in the array
   if let geometry = object["geometry"] as? Dictionary<String,Any>{
     // make sure it has location
     if let location = geometry["location"] as? Dictionary<String,Any>{

       // now get the lat or lng safely.
       let lat = location["lat"] as? String ?? "0.0" 
       let lng = location["lng"] as? String ?? "0.0"   

     }
   } 
  }
}

注意:永远不要使用强制解包!因为如果出现问题或者找不到特定对象,您的应用会崩溃,请确保至少使用guard letif let,尽管这是手动解析,您可以查看Swift 4 new {{3 }}

答案 2 :(得分:0)

考虑到你有一个数据数组作为结果(jsonResult),开始访问你的数组并确定每个参数的类型。

if let resultArray = jsonResult["results"] as? NSArray {
        for aResult in resultArray {

            //using "if let" simply means, in this case, if "geometry" is indeed a dictionary it will execute the statement/s inside this "if" block.
            if let geometry = aResult["geometry"] as? NSDictionary {
                if let location = geometry["location"] as? NSDictionary {
                    if let latValue = location["lat"] as? String {
                        //This will only be executed if the value is String
                        print(latValue)
                    }

                    if let lngValue = location["lng"] as? String {
                        print(lngValue)
                    }
                }
            }
        }
    }