如何在 Swift 中解析来自 Alamofire API 的 JSON 响应?

下面的代码我已经写了,我也得到了 JSON 的响应,但类型的 JSON 是“ AnyObject”,我不能转换成数组,所以我可以使用它。

Alamofire.request(.POST, "MY URL", parameters:parameters, encoding: .JSON) .responseJSON
{
(request, response, JSON, error) in


println(JSON?)
}
220166 次浏览

我既不是 JSON 专家,也不是 Swift 专家,但以下内容对我很有用。:)我已经从我当前的应用程序中提取了代码,只改变了“ MyLog to println”,并缩进了空格,使其显示为一个代码块(希望我没有破坏它)。

func getServerCourseVersion(){


Alamofire.request(.GET,"\(PUBLIC_URL)/vtcver.php")
.responseJSON { (_,_, JSON, _) in
if let jsonResult = JSON as? Array<Dictionary<String,String>> {
let courseName = jsonResult[0]["courseName"]
let courseVersion = jsonResult[0]["courseVersion"]
let courseZipFile = jsonResult[0]["courseZipFile"]


println("JSON:    courseName: \(courseName)")
println("JSON: courseVersion: \(courseVersion)")
println("JSON: courseZipFile: \(courseZipFile)")


}
}
}

希望这个能帮上忙。

编辑:

作为参考,下面是我的 PHP 脚本返回的内容:

[{"courseName": "Training Title","courseVersion": "1.01","courseZipFile": "101/files.zip"}]

如上所述,您可以使用 SwiftyJSON 库并获得您的值,就像我在下面所做的那样

Alamofire.request(.POST, "MY URL", parameters:parameters, encoding: .JSON) .responseJSON
{
(request, response, data, error) in


var json = JSON(data: data!)


println(json)
println(json["productList"][1])


}

我的 json 产品列表从脚本返回

{ "productList" :[


{"productName" : "PIZZA","id" : "1","productRate" : "120.00","productDescription" : "PIZZA AT 120Rs","productImage" : "uploads\/pizza.jpeg"},


{"productName" : "BURGER","id" : "2","productRate" : "100.00","productDescription" : "BURGER AT Rs 100","productImage" : "uploads/Burgers.jpg"}
]
}

产出:

{
"productName" : "BURGER",
"id" : "2",
"productRate" : "100.00",
"productDescription" : "BURGER AT Rs 100",
"productImage" : "uploads/Burgers.jpg"
}

我在 GitHub 上找到了 Swift2的答案

Https://github.com/alamofire/alamofire/issues/641

Alamofire.request(.GET, URLString, parameters: ["foo": "bar"])
.responseJSON { request, response, result in
switch result {
case .Success(let JSON):
print("Success with JSON: \(JSON)")


case .Failure(let data, let error):
print("Request failed with error: \(error)")


if let data = data {
print("Response data: \(NSString(data: data, encoding: NSUTF8StringEncoding)!)")
}
}
}

Swift 2.0 Alamofire 3.0的答案应该是这样的:

Alamofire.request(.POST, url, parameters: parameters, encoding:.JSON).responseJSON
{ response in switch response.result {
case .Success(let JSON):
print("Success with JSON: \(JSON)")


let response = JSON as! NSDictionary


//example if there is an id
let userId = response.objectForKey("id")!


case .Failure(let error):
print("Request failed with error: \(error)")
}
}

Https://github.com/alamofire/alamofire/blob/master/documentation/alamofire%203.0%20migration%20guide.md

Alamofire 4.0和 Swift 3.0的更新:

Alamofire.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default)
.responseJSON { response in
print(response)
//to get status code
if let status = response.response?.statusCode {
switch(status){
case 201:
print("example success")
default:
print("error with response status: \(status)")
}
}
//to get JSON return value
if let result = response.result.value {
let JSON = result as! NSDictionary
print(JSON)
}


}

我找到了一种方法,可以将 response. result. value (在 Alamofire response seJSON 闭包中)转换为我在应用程序中使用的 JSON 格式。

我用的是 Alamofire 3和 Swift 2.2。

下面是我使用的代码:

    Alamofire.request(.POST, requestString,
parameters: parameters,
encoding: .JSON,
headers: headers).validate(statusCode: 200..<303)
.validate(contentType: ["application/json"])
.responseJSON { (response) in
NSLog("response = \(response)")


switch response.result {
case .Success:
guard let resultValue = response.result.value else {
NSLog("Result value in response is nil")
completionHandler(response: nil)
return
}


let responseJSON = JSON(resultValue)


// I do any processing this function needs to do with the JSON here


// Here I call a completionHandler I wrote for the success case
break
case .Failure(let error):
NSLog("Error result: \(error)")
// Here I call a completionHandler I wrote for the failure case
return
}

我通常使用 光泽库在 iOS 中序列化或反序列化 JSON。例如,我有这样的 JSON:

{"ABDC":[{"AB":"qwerty","CD":"uiop"}],[{"AB":"12334","CD":"asdf"}]}

首先,我用 Gloss 结构对 JSON 数组建模:

Struct Struct_Name: Decodable {
let IJ: String?
let KL: String?
init?(json: JSON){
self.IJ = "AB" <~~ json
self.KL = "CD" <~~ json
}
}

然后在 Alamofire 回复 json,我做了以下事情:

Alamofire.request(url, method: .get, paramters: parametersURL).validate(contentType: ["application/json"]).responseJSON{ response in
switch response.result{
case .success (let data):
guard let value = data as? JSON,
let eventsArrayJSON = value["ABDC"] as? [JSON]
else { fatalError() }
let struct_name = [Struct_Name].from(jsonArray: eventsArrayJSON)//the JSON deserialization is done here, after this line you can do anything with your JSON
for i in 0 ..< Int((struct_name?.count)!) {
print((struct_name?[i].IJ!)!)
print((struct_name?[i].KL!)!)
}
break


case .failure(let error):
print("Error: \(error)")
break
}
}

以上代码的输出:

qwerty
uiop
1234
asdf
 pod 'Alamofire'
pod 'SwiftyJSON'
pod 'ReachabilitySwift'






import UIKit
import Alamofire
import SwiftyJSON
import SystemConfiguration


class WebServiceHelper: NSObject {


typealias SuccessHandler = (JSON) -> Void
typealias FailureHandler = (Error) -> Void


// MARK: - Internet Connectivity


class func isConnectedToNetwork() -> Bool {


var zeroAddress = sockaddr_in()
zeroAddress.sin_len = UInt8(MemoryLayout<sockaddr_in>.size)
zeroAddress.sin_family = sa_family_t(AF_INET)


guard let defaultRouteReachability = withUnsafePointer(to: &zeroAddress, {
$0.withMemoryRebound(to: sockaddr.self, capacity: 1) {
SCNetworkReachabilityCreateWithAddress(nil, $0)
}
}) else {
return false
}


var flags: SCNetworkReachabilityFlags = []
if !SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags) {
return false
}


let isReachable = flags.contains(.reachable)
let needsConnection = flags.contains(.connectionRequired)


return (isReachable && !needsConnection)
}


// MARK: - Helper Methods


class func getWebServiceCall(_ strURL : String, isShowLoader : Bool, success : @escaping SuccessHandler, failure : @escaping FailureHandler)
{
if isConnectedToNetwork() {


print(strURL)


if isShowLoader == true {


AppDelegate.getDelegate().showLoader()
}


Alamofire.request(strURL).responseJSON { (resObj) -> Void in


print(resObj)


if resObj.result.isSuccess {
let resJson = JSON(resObj.result.value!)


if isShowLoader == true {
AppDelegate.getDelegate().dismissLoader()
}


debugPrint(resJson)
success(resJson)
}
if resObj.result.isFailure {
let error : Error = resObj.result.error!


if isShowLoader == true {
AppDelegate.getDelegate().dismissLoader()
}
debugPrint(error)
failure(error)
}
}
}else {




CommonMethods.showAlertWithError("", strMessage: Messages.NO_NETWORK, withTarget: (AppDelegate.getDelegate().window!.rootViewController)!)
}
}


class func getWebServiceCall(_ strURL : String, params : [String : AnyObject]?, isShowLoader : Bool, success : @escaping SuccessHandler,  failure :@escaping FailureHandler){
if isConnectedToNetwork() {


if isShowLoader == true {
AppDelegate.getDelegate().showLoader()
}




Alamofire.request(strURL, method: .get, parameters: params, encoding: JSONEncoding.default, headers: nil).responseJSON(completionHandler: {(resObj) -> Void in


print(resObj)


if resObj.result.isSuccess {
let resJson = JSON(resObj.result.value!)


if isShowLoader == true {
AppDelegate.getDelegate().dismissLoader()
}


success(resJson)
}
if resObj.result.isFailure {
let error : Error = resObj.result.error!


if isShowLoader == true {
AppDelegate.getDelegate().dismissLoader()
}


failure(error)
}


})
}
else {


CommonMethods.showAlertWithError("", strMessage: Messages.NO_NETWORK, withTarget: (AppDelegate.getDelegate().window!.rootViewController)!)
}


}






class func postWebServiceCall(_ strURL : String, params : [String : AnyObject]?, isShowLoader : Bool, success : @escaping SuccessHandler, failure :@escaping FailureHandler)
{
if isConnectedToNetwork()
{


if isShowLoader == true
{
AppDelegate.getDelegate().showLoader()
}


Alamofire.request(strURL, method: .post, parameters: params, encoding: JSONEncoding.default, headers: nil).responseJSON(completionHandler: {(resObj) -> Void in


print(resObj)


if resObj.result.isSuccess
{
let resJson = JSON(resObj.result.value!)


if isShowLoader == true
{
AppDelegate.getDelegate().dismissLoader()
}


success(resJson)
}


if resObj.result.isFailure
{
let error : Error = resObj.result.error!


if isShowLoader == true
{
AppDelegate.getDelegate().dismissLoader()
}


failure(error)
}
})
}else {
CommonMethods.showAlertWithError("", strMessage: Messages.NO_NETWORK, withTarget: (AppDelegate.getDelegate().window!.rootViewController)!)
}
}




class func postWebServiceCallWithImage(_ strURL : String, image : UIImage!, strImageParam : String, params : [String : AnyObject]?, isShowLoader : Bool, success : @escaping SuccessHandler, failure : @escaping FailureHandler)
{
if isConnectedToNetwork() {
if isShowLoader == true
{
AppDelegate.getDelegate().showLoader()
}


Alamofire.upload(
multipartFormData: { multipartFormData in
if let imageData = UIImageJPEGRepresentation(image, 0.5) {
multipartFormData.append(imageData, withName: "Image.jpg")
}


for (key, value) in params! {


let data = value as! String


multipartFormData.append(data.data(using: String.Encoding.utf8)!, withName: key)
print(multipartFormData)
}
},
to: strURL,
encodingCompletion: { encodingResult in
switch encodingResult {
case .success(let upload, _, _):
upload.responseJSON { response in
debugPrint(response)
//let datastring = String(data: response, encoding: String.Encoding.utf8)
// print(datastring)
}
case .failure(let encodingError):
print(encodingError)
if isShowLoader == true
{
AppDelegate.getDelegate().dismissLoader()
}


let error : NSError = encodingError as NSError
failure(error)
}


switch encodingResult {
case .success(let upload, _, _):
upload.responseJSON { (response) -> Void in


if response.result.isSuccess
{
let resJson = JSON(response.result.value!)


if isShowLoader == true
{
AppDelegate.getDelegate().dismissLoader()
}


success(resJson)
}


if response.result.isFailure
{
let error : Error = response.result.error! as Error


if isShowLoader == true
{
AppDelegate.getDelegate().dismissLoader()
}


failure(error)
}


}
case .failure(let encodingError):
if isShowLoader == true
{
AppDelegate.getDelegate().dismissLoader()
}


let error : NSError = encodingError as NSError
failure(error)
}
}
)
}
else
{
CommonMethods.showAlertWithError("", strMessage: Messages.NO_NETWORK, withTarget: (AppDelegate.getDelegate().window!.rootViewController)!)
}
}


}




==================================




Call Method




let aParams : [String : String] = [
"ReqCode" : Constants.kRequestCodeLogin,
]


WebServiceHelper.postWebServiceCall(Constants.BaseURL, params: aParams as [String : AnyObject]?, isShowLoader: true, success: { (responceObj) in




if "\(responceObj["RespCode"])" != "1"
{
let alert = UIAlertController(title: Constants.kAppName, message: "\(responceObj["RespMsg"])", preferredStyle: UIAlertControllerStyle.alert)
let OKAction = UIAlertAction(title: "OK", style: .default) { (action:UIAlertAction!) in
}
alert.addAction(OKAction)
self.present(alert, animated: true, completion: nil)
}
else
{
let aParams : [String : String] = [
"Password" : self.dictAddLogin[AddLoginConstants.kPassword]!,
]
CommonMethods.saveCustomObject(aParams as AnyObject?, key: Constants.kLoginData)


}
}, failure:
{ (error) in


CommonMethods.showAlertWithError(Constants.kALERT_TITLE_Error, strMessage: error.localizedDescription,withTarget: (AppDelegate.getDelegate().window!.rootViewController)!)
})
}

雨燕3

pod 'Alamofire', '~> 4.4'
pod 'SwiftyJSON'


File json format:
{
"codeAd": {
"dateExpire": "2017/12/11",
"codeRemoveAd":"1231243134"
}
}


import Alamofire
import SwiftyJSON
private func downloadJson() {
Alamofire.request("https://yourlinkdownloadjson/abc").responseJSON { response in
debugPrint(response)


if let json = response.data {
let data = JSON(data: json)
print("data\(data["codeAd"]["dateExpire"])")
print("data\(data["codeAd"]["codeRemoveAd"])")
}
}
}

Swift 3、 Alamofire 4.4和 SwiftyJSON:

Alamofire.request(url, method: .get)
.responseJSON { response in
if response.data != nil {
let json = JSON(data: response.data!)
let name = json["people"][0]["name"].string
if name != nil {
print(name!)
}
}
}

它将解析这个 JSON 输入:

{
people: [
{ name: 'John' },
{ name: 'Dave' }
]
}

这是用 Xcode 10.1和 Swift 4构建的

完美的组合“ Alamofire”(4.8.1)和“ SwiftyJSON”(4.2.0)

pod 'Alamofire'pod 'SwiftyJSON'

JSON 格式的服务器响应:

{
"args": {},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip;q=1.0, compress;q=0.5",
"Accept-Language": "en;q=1.0",
"Host": "httpbin.org",
"User-Agent": "AlamoFire TEST/1.0 (com.ighost.AlamoFire-TEST; build:1; iOS 12.1.0) Alamofire/4.8.1"
},
"origin": "200.55.140.181, 200.55.140.181",
"url": "https://httpbin.org/get"
}

在这种情况下,我想打印“主机”信息: “主机”: “ httpbin.org”

Alamofire.request("https://httpbin.org/get").validate().responseJSON { response in
switch response.result {
case .success:
print("Validation Successful)")


if let json = response.data {
do{
let data = try JSON(data: json)
let str = data["headers"]["Host"]
print("DATA PARSED: \(str)")
}
catch{
print("JSON Error")
}


}
case .failure(let error):
print(error)
}
}

保持冷静和快乐代码

在快速5中,我们喜欢使用 typealias 来完成。 Typlealias 没有什么只是用来清理代码。

typealias response = (Bool,Any?)->()




static func postCall(_ url : String, param : [String : Any],completion : @escaping response){
Alamofire.request(url, method: .post, parameters: param, encoding: JSONEncoding.default, headers: [:]).responseJSON { (response) in


switch response.result {
case .success(let JSON):
print("\n\n Success value and JSON: \(JSON)")


case .failure(let error):
print("\n\n Request failed with error: \(error)")


}
}
}

Swift 5

class User: Decodable {


var name: String
var email: String
var token: String


enum CodingKeys: String, CodingKey {
case name
case email
case token
}


public required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.name = try container.decode(String.self, forKey: .name)
self.email = try container.decode(String.self, forKey: .email)
self.token = try container.decode(String.self, forKey: .token)
}
}

Alamofire API

    Alamofire.request("url.endpoint/path", method: .get, parameters: params, encoding: URLEncoding.queryString, headers: nil)
.validate()
.responseJSON { response in


switch (response.result) {


case .success( _):


do {
let users = try JSONDecoder().decode([User].self, from: response.data!)
print(users)


} catch let error as NSError {
print("Failed to load: \(error.localizedDescription)")
}


case .failure(let error):
print("Request error: \(error.localizedDescription)")
}

简单的答案是让 AlamoFire 直接进行解码。

令人惊讶的是,您没有使用. response seJSON,因为它返回一个非类型化的 json 对象

相反,您使您的对象可解码-并要求 AF 直接解码到他们

我的 json 响应包含 Account 对象的数组。我只关心 id 和 name 键(尽管还有更多的键)

struct Account:Codable {
let id:Int
let name:String
}

那么简单

    AF.request(url,
method: .get)
.responseDecodable(of:[Account].self) { response in
switch response.result {
case .success:
switch response.response?.statusCode {
case 200:
//response.value is of type [Account]
default:
//handle other cases
}
case let .failure(error):
//probably the decoding failed because your json doesn't match the expected format
}
}
let semaphore = DispatchSemaphore (value: 0)


var request = URLRequest(url: URL(string: Constant.localBaseurl2 + "compID")!,timeoutInterval: Double.infinity)
request.httpMethod = "GET"
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let response = response {
let nsHTTPResponse = response as! HTTPURLResponse
print(nsHTTPResponse)
                                          

}
if let error = error {
print ("\(error)")
return
}
                                

if let data = data {
DispatchQueue.main.async {
                                        

let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase//or any other Decoder\
                                        

do{
                                            

let jsonDecoder = JSONDecoder()
let memberRecord = try jsonDecoder.decode(COMPLAINTSVC.GetComplaints.self, from: data)
print(memberRecord.message)
                                         

for detailData in memberRecord.message{
print(detailData)
                                                

                                                

                                                

                                                

                                            

}
                                            

                                            

                                            

}catch{
                                            

print(error.localizedDescription)
}
                                        

                                      

                                        

}
                             

}
                              

semaphore.signal()
}


task.resume()
semaphore.wait()

}