2016-07-15 97 views
0

我正在使用Google的geolocator API自動映射某些內容。它在請求中返回一個JSON字符串,但我在分析它時遇到了很多困難。我嘗試過像Freddy和SwiftyJSON這樣的東西,但無法提取我想要的字段。Swift JSON解析 - 無法訪問字段/返回無

這裏是我的代碼示例:

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

我試圖讓現場結果.geometry.location。使用Freddy JSON解析庫,我能夠獲得結果字段,但無法訪問幾何字段。有人可以看看這個,看看我做錯了什麼嗎? SwiftyJSON甚至不讓我解析JSON。

回答

2

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

一個說明,參數和變量是小寫。只有類名應該是大寫的。

+0

感謝您的提示!不幸的是,這並不能解決我的json解析問題,但很高興知道我可以通過回調將該數據傳遞迴UI。 –

+0

@FKunecke,我更新瞭解析正確的答案。你的方法在操場上可能看起來更好,但在現實生活中,你的實現會阻止會導致應用程序的UI凍結的主線程。 –

0

這是一個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,使之簡單。

-1

我的代碼與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) 
    } 
} 
+0

你不應該像現在這樣使用你的'sendJsonRequest'。這是一個可怕的實施。再看一遍,按照SushiGrass Jacob的回答。 – OOPer