【问题标题】:Swift JSON Parsing - Unable to access field/returns nilSwift JSON Parsing - 无法访问字段/返回 nil
【发布时间】:2016-07-15 20:10:55
【问题描述】:

我正在使用 Google 的地理定位器 API 来自动映射一些东西。它在请求中返回一个 JSON 字符串,但我在解析它时遇到了很多困难。我尝试过 Freddy 和 SwiftyJSON 之类的东西,但都无法提取我想要的字段。

这是我的代码示例:

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()

这是我从单独的 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"
}

我正在尝试获取字段 results.geometry.location。使用 Freddy JSON 解析库,我能够获取结果字段,但无法访问几何字段。有人可以看看这个,看看我做错了什么吗? SwiftyJSON 甚至不允许我解析 JSON。

【问题讨论】:

    标签: json swift swifty-json


    【解决方案1】:

    dataTaskWithRequest 中作为参数传递的闭包是异步的,这意味着它可以立即被调用,或者在给定网络条件的情况下被调用。最好在你原来的sendJsonRequest 方法中传递一个闭包,同时返回void。调用 dataTaskWithResult 闭包后,您可以使用响应调用闭包。

    就代码而言,它可能如下所示:

    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…
        }
    }
    

    注意,参数和变量都是小写的。只有类名应该是大写的。

    【讨论】:

    • 感谢您的提示!不幸的是,这并不能解决我的 json 解析问题,但很高兴知道我可以在回调中将该数据传回 UI。
    • @FKunecke,我用更正的解析更新了答案。您的方法在操场上可能看起来更好,但在现实生活中,您的实现将阻塞主线程,这将导致应用程序的 UI 冻结。
    【解决方案2】:

    这是一个 javascript 对象,您可以执行以下操作来检索信息

    将结果赋值给变量

    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}
    

    你可以使用 JSON.stringify 让它变得简单。

    【讨论】:

      【解决方案3】:

      我的代码可以与 Freddy JSON 库一起使用。这是我的新代码,以防万一有人遇到类似问题:

      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)
          }
      }
      

      【讨论】:

      • 您不应照原样使用您的sendJsonRequest。这是一个糟糕的实现。再次查看并关注 SushiGrass Jacob 的回答。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-04
      • 1970-01-01
      相关资源
      最近更新 更多