简体   繁体   English

Swift JSON解析-无法访问字段/返回nil

[英]Swift JSON Parsing - Unable to access field/returns nil

I'm using Google's geolocator API to map some stuff automatically. 我正在使用Google的geolocator API自动映射某些内容。 It returns a JSON string in the request, but I'm having a lot of difficulty parsing it. 它在请求中返回JSON字符串,但是在解析它时有很多困难。 I've tried things like Freddy and SwiftyJSON but can't get either to extract the field I want. 我已经尝试过诸如Freddy和SwiftyJSON之类的事情,但都无法提取我想要的字段。

Here's a sample of my code: 这是我的代码示例:

func sendJsonRequest(ConnectionString: String,
                              HTTPMethod : HttpMethod = HttpMethod.Get,
                              JsonHeaders : [String : String] = [ : ],
                              JsonString: String = "") -> NSData? {

    // create the request & response
    let request = NSMutableURLRequest(URL: NSURL(string: ConnectionString)!, cachePolicy: NSURLRequestCachePolicy.ReloadIgnoringLocalCacheData, timeoutInterval: 5)

    // create some JSON data and configure the request
    let jsonString = JsonString;
    request.HTTPBody = jsonString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)

    // handle both get and post
    request.HTTPMethod = HTTPMethod.rawValue

    // we'll always be sending json so this is fine
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")

    // add the headers.  If there aren't any then that's ok
    for item in JsonHeaders {
        request.addValue(item.1, forHTTPHeaderField: item.0)
    }
    print("Request:")
    print(request)

    let session = NSURLSession.sharedSession()
    var data : NSData?

    var urlTask = session.dataTaskWithRequest(request) { (Data, Response, Error) in
        data = Data
    }
    urlTask.resume()

    while (data == nil) {

    }

    return data

}

// return the coordinates of a given location
func getCoordinates() -> Coordinates {
    var result = Coordinates()

    let ConnectionString = "https://maps.googleapis.com/maps/api/geocode/json?address=43201"
    let jsondata = sendJsonRequest(ConnectionString)

    let data = jsondata

    let json = JSON(data!)

    print(json)


    return result
}

getCoordinates()

Here's an example of the output I'm getting from a separate JSON client: 这是我从另一个JSON客户端获得的输出示例:

{
"results": [
    {
        "address_components": [
            {
                "long_name": "43201",
                "short_name": "43201",
                "types": [
                    "postal_code"
                ]
            },
            {
                "long_name": "Columbus",
                "short_name": "Columbus",
                "types": [
                    "locality",
                    "political"
                ]
            },
            {
                "long_name": "Franklin County",
                "short_name": "Franklin County",
                "types": [
                    "administrative_area_level_2",
                    "political"
                ]
            },
            {
                "long_name": "Ohio",
                "short_name": "OH",
                "types": [
                    "administrative_area_level_1",
                    "political"
                ]
            },
            {
                "long_name": "United States",
                "short_name": "US",
                "types": [
                    "country",
                    "political"
                ]
            }
        ],
        "formatted_address": "Columbus, OH 43201, USA",
        "geometry": {
            "bounds": {
                "northeast": {
                    "lat": 40.011147,
                    "lng": -82.9723898
                },
                "southwest": {
                    "lat": 39.976962,
                    "lng": -83.0250691
                }
            },
            "location": {
                "lat": 39.9929821,
                "lng": -83.00122100000002
            },
            "location_type": "APPROXIMATE",
            "viewport": {
                "northeast": {
                    "lat": 40.011147,
                    "lng": -82.9723898
                },
                "southwest": {
                    "lat": 39.976962,
                    "lng": -83.0250691
                }
            }
        },
        "place_id": "ChIJ9Rz24rWOOIgR3EEuL2Ge4oo",
        "types": [
            "postal_code"
        ]
    }
],
"status": "OK"
}

I'm trying to get the field results.geometry.location. 我正在尝试获取字段results.geometry.location。 Using the Freddy JSON parsing library I was able to get the results field but I couldn't access the geometry field. 使用Freddy JSON解析库,我可以获取结果字段,但是无法访问几何字段。 Can someone take a look at this to see if I'm doing something wrong? 有人可以看看这个,看看我做错了什么吗? SwiftyJSON doesn't even let me parse the JSON. SwiftyJSON甚至都不让我解析JSON。

The closure passed as an argument in dataTaskWithRequest is asynchronous meaning that it could be called instantly or way down the road given network conditions. dataTaskWithRequest作为参数传递的闭包是异步的,这意味着它可以立即调用,也可以在给定网络条件的情况下调用。 It would be better to pass a closure in your original sendJsonRequest method while return void . 最好在原始的sendJsonRequest方法中传递一个闭包,同时返回void Once the dataTaskWithResult closure is called, you can invoke your closure with the response. 调用dataTaskWithResult闭包后,您可以使用响应调用闭包。

In terms of code, it might look like this: 在代码方面,它可能看起来像这样:

func sendJsonRequest(connectionString: String,
                              httpMethod : HttpMethod = HttpMethod.Get,
                              jsonHeaders : [String : String] = [ : ],
                              jsonString: String = "",
                              completion: (data: NSData?, error: NSError?) -> Void) {
   … //Your code
    var urlTask = session.dataTaskWithRequest(request) { (optionalData, optionalResponse, optionalError) in
        NSOperationQueue.mainQueue().addOperation {
            if let data = optionalData {
            completion(data, nil)
            }
            else if let error = optionalError {
            completion(nil, error)
            }
        }
    }
    urlTask.resume()
}

// return the coordinates of a given location
func getCoordinates(withCompletion completion: (Coordinates) -> Void) {

    let connectionString = "https://maps.googleapis.com/maps/api/geocode/json?address=43201"
    sendJsonRequest(connectionString: connectionString) {
        (optionalData, optionalError) in
        if let data = optionalData {
            let json = JSON(data)
            print(json)
            //Do your conversion to Coordinates here
            let coordinates = //?
            completion(coordinates)
        }
        // Handle errors, etc…
    }
}

One note, arguments and variables are lowercased. 请注意,参数和变量均为小写。 Only class names should be uppercase. 仅类别名称应为大写。

It's a javascript object, you can do the below to retrive information 这是一个javascript对象,您可以执行以下操作以获取信息

Assign the result to a variable 将结果分配给变量

var results = {
"results": [
    {
        "address_components": [
            {
                "long_name": "43201",
                "short_name": "43201",
                "types": [
                    "postal_code"
                ]
            },
            {
                "long_name": "Columbus",
                "short_name": "Columbus",
                "types": [
                    "locality",
                    "political"
                ]
            },
            {
                "long_name": "Franklin County",
                "short_name": "Franklin County",
                "types": [
                    "administrative_area_level_2",
                    "political"
                ]
            },
            {
                "long_name": "Ohio",
                "short_name": "OH",
                "types": [
                    "administrative_area_level_1",
                    "political"
                ]
            },
            {
                "long_name": "United States",
                "short_name": "US",
                "types": [
                    "country",
                    "political"
                ]
            }
        ],
        "formatted_address": "Columbus, OH 43201, USA",
        "geometry": {
            "bounds": {
                "northeast": {
                    "lat": 40.011147,
                    "lng": -82.9723898
                },
                "southwest": {
                    "lat": 39.976962,
                    "lng": -83.0250691
                }
            },
            "location": {
                "lat": 39.9929821,
                "lng": -83.00122100000002
            },
            "location_type": "APPROXIMATE",
            "viewport": {
                "northeast": {
                    "lat": 40.011147,
                    "lng": -82.9723898
                },
                "southwest": {
                    "lat": 39.976962,
                    "lng": -83.0250691
                }
            }
        },
        "place_id": "ChIJ9Rz24rWOOIgR3EEuL2Ge4oo",
        "types": [
            "postal_code"
        ]
    }
],
"status": "OK"
};



console.log(results); // you can see the object
Object {results: Array[1], status: "OK"}
console.log(results.results[0]); // Accessing the first object inside the array
Object {address_components: Array[5], formatted_address: "Columbus, OH 43201, USA", geometry: Object, place_id: "ChIJ9Rz24rWOOIgR3EEuL2Ge4oo", types: Array[1]}
console.log(results.results[0].geometry); // Accessing the geometry object.
Object {bounds: Object, location: Object, location_type: "APPROXIMATE", viewport: Object}

you can use JSON.stringify to make it simple. 您可以使用JSON.stringify使其变得简单。

I got my code to work with the Freddy JSON library. 我得到了与Freddy JSON库一起使用的代码。 Here's my new code, in case anyone runs into a similar issue: 如果有人遇到类似问题,这是我的新代码:

func getCoordinates(address: String) -> Coordinates {
    var result = Coordinates()

    let ConnectionString = _connectionUrl + address
    let jsondata = sendJsonRequest(ConnectionString)

    //print(json)
    // returns a [string : AnyObject]
    let data = jsondata
    do {
        let json = try JSON(data: data!)
        let results = try json.array("results")[0]

        let geometry = try results.dictionary("geometry")
        print(geometry)
        let location = geometry["location"]!

        print(location)
        let lat = try location.double("lat")
        let lng = try location.double("lng")

        result.Latitude = lat
        result.Longitude = lng

    } catch {
        let nsError = error as NSError
        print(nsError.localizedDescription)
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM