如何在Swift中使用Alamofire API解析JSON响应?

138

我已经编写了以下代码,我也能够获得JSON响应,但是JSON的类型是“AnyObject”,我无法将其转换为数组以便我可以使用它。

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

    println(JSON?)
}

我没有给你的问题投反对票,但我认为这是因为解析JSON是一个过于广泛的主题,无法给出清晰、直接的答案。试试这个叫做SwiftyJSON的库。 - Isuru
@Isuru 没关系!我看过那个库,但我正在使用Alamofire!你能否给我发送一下你使用SwiftyJson的示例代码?因为他们的代码对我没用! - Developer
我也使用Alamofire和SwiftyJSON。我只需像这样传递响应 let data = JSONValue(JSON!),然后就可以像这样提取值 data["Id"]。SwiftyJSON文档提供了如何以所需类型检索这些值的示例。你具体遇到了什么错误? - Isuru
14个回答

165

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

        }

17
如何获取JSON的实际内容?这是什么类型的对象?设计和文档如此晦涩,我无法理解,也找不到互联网上的任何示例... - Alex Worden
我在我的答案中添加了几行应该会有帮助的代码。 - Joseph Geraghty
@JosephGeraghty 在编码参数中加入结果,编译器告诉我有一个额外的参数调用... 有什么想法吗? - dispatchswift
1
@AlexWorden同意,这个页面帮助我回答了那些问题并提供了一个不错的解决方案:https://github.com/SwiftyJSON/SwiftyJSON - iljn
更新后的Swift 3答案是一个糟糕的例子。不要在Swift 3中使用NSDictionary,而应该使用Swift字典。 - rmaddy
显示剩余2条评论

32

如上所述,您可以使用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"
}

我尝试在安装后使用SwiftyJson,但在SwiftyJson文件中出现了一些300错误,有人遇到过这个问题吗?我正在使用Xcode版本6.2,iOS版本8.1,cocoaPods 36,如github文档中所述。 - Sashi
2
兄弟,有什么错误吗?请提出一个单独的问题并提供一些细节。如果可能的话,请使用SwiftyJSON,它就像魔法一样美丽。 - Zia
应该将JSON字符串转换为具体的Swift对象,以便您可以自然地清晰地使用它。通过字符串名称访问字段是荒谬的且容易出错。 - The Muffin Man

31

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' }
  ]
}

还有一个Alamofire Swifty-JSON特定的插件,它消除了显式的JSON()转换的必要:https://github.com/SwiftyJSON/Alamofire-SwiftyJSON - Robin Macharg
这对我有帮助,但我在使用JSON方法时遇到了一些问题,因为它会抛出异常。 - iGhost

25

我在 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)!)")
            }
        }
    }

3
这是适用于Swift 2.0+和Alamofire的JSON解析的正确版本。 - Saqib Omer
5
嗯,我仍然遇到了编译失败的错误信息:“(_, _, _) -> Void”无法转换为“Response<AnyObject, NSError> -> Void”。请问您需要我帮忙翻译吗? - alex
@alex 请查看这个答案,了解我用来解决它的方法。 - Joseph
非常感谢!你不知道我尝试了多少次才能正确显示来自服务器的响应消息,你是我的救命恩人! - thibaut noah

17

我既不是JSON专家,也不是Swift专家,但以下内容对我有效。 :) 我从我的当前应用程序中提取了代码,并仅将"MyLog"更改为"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"}]

这应该是被选中的答案,尽管您可能希望更新它,因为Alamofire已经稍微更新了他们的方法。 - Snymax

17

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

1
如果您有一个“可解码”的类型,应该使用responseDecodable而不是responseJSON - Jon Shier

11

Swift 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"])")
            }
        }
    }

7

此项目使用Xcode 10.1和Swift 4构建

完美组合"Alamofire"(4.8.1) 和 "SwiftyJSON"(4.2.0),首先您需要安装这两个pod

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

在这种情况下,我想打印“Host”信息:"Host": "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)
        }
    }

保持冷静,愉快地编写代码


1
谢谢。我已经使用并重新格式化以适应我的项目需求,我可以证明这仍然适用于Swift 5。 - Jiraheta

2

我找到了一种方法,可以将Alamofire responseJSON闭包中的response.result.value转换为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
        }

2

我通常使用Gloss库在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的responseJSON中,我执行以下操作:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接