Wie analysiere ich die JSON-Antwort von der Alamofire-API in Swift?

125

Der folgende Code, den ich geschrieben habe, und ich erhalte auch eine Antwort in JSON, aber der JSON-Typ ist "AnyObject" und ich kann ihn nicht in Array konvertieren, damit ich ihn verwenden kann.

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

    println(JSON?)
}
Entwickler
quelle
Ich habe Ihre Frage nicht abgelehnt, aber ich gehe davon aus, dass das Parsen von JSON zu weit gefasst ist, um eine klare, klare Antwort zu geben. Probieren Sie diese Bibliothek namens SwiftyJSON aus .
Isuru
@ Isuru Es ist OK! Ich habe diese Bibliothek gesehen, aber ich benutze Alamofire! Aber können Sie mir den Beispielcode senden, in dem Sie den SwiftyJson verwendet haben? Dort hat Code bei mir nicht funktioniert!
Entwickler
Ich benutze auch SwiftyJSON zusammen mit Alamofire. Ich gebe die Antwort einfach so weiter let data = JSONValue(JSON!). Dann kann ich solche Werte extrahieren data["Id"]. Die SwiftyJSON-Dokumentation enthält Beispiele zum Abrufen dieser Werte in den gewünschten Typen. Was genau ist der Fehler, den Sie bekommen?
Isuru

Antworten:

160

Die Antwort für Swift 2.0 Alamofire 3.0 sollte eigentlich eher so aussehen:

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

UPDATE für Alamofire 4.0 und 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)
            }

        }
Joseph Geraghty
quelle
13
Wie kommen Sie zum eigentlichen Inhalt von JSON? Was für ein Objekt ist das? Das Design und die Dokumentation sind so dunkel, dass ich es nicht herausfinden und keine Beispiele im Internet finden kann ...
Alex Worden
Ich habe meiner Antwort ein paar Zeilen hinzugefügt, die helfen sollen.
Joseph Geraghty
@JosephGeraghty Der Codierungsparameter führt dazu, dass der Compiler mir mitteilt, dass es einen zusätzlichen Argumentaufruf gibt ... Irgendeine Idee?
Amariduran
@ jch-duran nicht positiv, aber ich erinnere mich vage, dass ich vor einiger Zeit auf etwas Ähnliches gestoßen bin. Ich denke, es hatte etwas damit zu tun, dass die Bibliotheken nicht aktualisiert wurden oder mit der schnellen Version möglicherweise nicht aktuell sind. Es könnte hilfreich sein, sicherzustellen, dass Sie auf den neuesten Versionen sind
Joseph Geraghty
1
@AlexWorden stimmte zu, diese Seite half mir bei der Beantwortung dieser Fragen und bietet eine
gute
31

Wie oben erwähnt, können Sie die SwiftyJSON-Bibliothek verwenden und Ihre Werte erhalten, wie ich es unten getan habe

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

}

Meine JSON-Produktliste kehrt vom Skript zurück

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

Ausgabe :

{
  "productName" : "BURGER",
  "id" : "2",
  "productRate" : "100.00",
  "productDescription" : "BURGER AT Rs 100",
  "productImage" : "uploads/Burgers.jpg"
}
Vikram Pote
quelle
Ich versuche, das SwiftyJson-Ding nach der Installation zu verwenden, gebe aber 300 Fehler in der SwiftyJson-Datei an. Hat sich jemand dem Problem gestellt? i 'unter Verwendung von Xcode Version 6.2, ios Version 8.1, cocoaPods 36, wie in der Dokumentation zu [github] ( github.com/SwiftyJSON/SwiftyJSON ) erwähnt.
Sashi
2
Kumpel. Was sind die Fehler? Stellen Sie eine separate Frage und geben Sie einige Details an. SwiftyJSON ist so schön wie Magie. Verwenden Sie es wenn möglich.
Zia
Eigentlich sollte die JSON-Zeichenfolge in ein schnelles Betonobjekt konvertiert werden, damit Sie sie auf natürliche Weise sauber verwenden können. Der Zugriff auf Felder über ihren Zeichenfolgennamen ist lächerlich und fehleranfällig.
Der Muffin-Mann
26

Swift 3, Alamofire 4.4 und 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!)
        }
      }
  }

Dadurch wird diese JSON-Eingabe analysiert:

{
  people: [
    { name: 'John' },
    { name: 'Dave' }
  ]
}
iljn
quelle
Es gibt auch ein Alamofire Swifty-JSON-spezifisches Plugin, das die explizite JSON()Konvertierung
überflüssig macht
Dies hilft mir, aber ich hatte einige Probleme mit der JSON-Methode, weil Exception
iGhost
24

Ich habe die Antwort auf GitHub für Swift2 gefunden

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)!)")
            }
        }
    }
mick80234
quelle
3
Dies ist die richtige Version für Swift 2.0 + Alamofire JSON-Parsing.
Saqib Omer
5
hmm ich bin immer noch eine Fehlermeldung gebaut fail: '(_, _, _) -> Void' ist nicht konvertierbar 'Antwort <ANYOBJECT, NSError> -> Void'
alex
@alex In dieser Antwort erfahren Sie , was ich zur Lösung verwendet habe.
Joseph
Ich danke dir sehr ! Sie haben keine Ahnung, wie viele Dinge ich versucht habe, die Antwortnachricht vom Server richtig anzuzeigen, Lebensretter!
Thibaut Noah
17

Ich bin weder ein JSON-Experte noch ein Swift-Experte, aber das Folgende funktioniert für mich. :) Ich habe den Code aus meiner aktuellen App extrahiert und nur "MyLog in println" geändert und Leerzeichen eingerückt, damit er als Codeblock angezeigt wird (hoffentlich habe ich ihn nicht beschädigt).

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

          }
      }
}

Hoffe das hilft.

Bearbeiten:

Als Referenz gibt mein PHP-Skript Folgendes zurück:

[{"courseName": "Training Title","courseVersion": "1.01","courseZipFile": "101/files.zip"}]
KenL
quelle
Dies sollte die ausgewählte Antwort sein, obwohl Sie sie möglicherweise aktualisieren möchten, da Alamofire ihre Methoden ein wenig aktualisiert hat
Snymax
10

schnell 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"])")
            }
        }
    }
Giang
quelle
2

Ich habe eine Möglichkeit gefunden, den Wert response.result.value (innerhalb eines Alamofire responseJSON-Abschlusses) in das JSON-Format zu konvertieren, das ich in meiner App verwende.

Ich benutze Alamofire 3 und Swift 2.2.

Hier ist der Code, den ich verwendet habe:

    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
        }
Carl Smith
quelle
2

Normalerweise verwende ich die Gloss- Bibliothek, um JSON in iOS zu serialisieren oder zu deserialisieren. Zum Beispiel habe ich JSON, das so aussieht:

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

Zuerst modelliere ich das JSON-Array in der Gloss-Struktur:

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

Und dann mache ich in Alamofire responseJSON Folgendes:

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

Die Ausgabe des obigen Codes:

qwerty
uiop
1234
asdf
Luthfi Rahman
quelle
2

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)")
         }
Sazzad Hissain Khan
quelle
1

Dies wurde mit Xcode 10.1 und Swift 4 erstellt

Perfekte Kombination "Alamofire" (4.8.1) und "SwiftyJSON" (4.2.0). Zuerst sollten Sie beide Pods installieren

pod 'Alamofire' und pod 'SwiftyJSON'

Die Serverantwort im JSON-Format:

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

In diesem Fall möchte ich die "Host " -Info ausdrucken: "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)
        }
    }

Bleib ruhig und glücklich Code 😎

iGhost
quelle
0

In Swift 5 mögen wir Typealias für die Vervollständigung. Typlealias nichts nur zum Bereinigen des Codes.

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

           }
    }
}
Talha Rasool
quelle
-10
 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)!)
            })
        }
Nikunj Patel
quelle
6
Eine Erklärung, was all dieser Code ist, wäre hilfreich.
Peter.swallow