JSON.dictionaryObject is null in Alamofire swift 3 - json

I have a JSON in following format:
postJson ={"firstname":"Vishal","lastname":"raskar","username":"vishal123","password":"123456","confirmpassword":"123456","email":"raskarvishal7#gmail.com","timezone":"1","accountid":"12345","phoneno":"8655012753"}
(Data type of postJson is JSON i.e swiftyJSON)
Now I want to hit on server through Alamofire, so I need to Post JSON data in dictionary format in parameters : ___, e.g.:
Alamofire.request(URL, method: .post, parameters: postJson.dictionaryObject, encoding: JSONEncoding.default,headers: "Content-Type": "application/json").responseJSON { response in switch response.result {
case .success(let data):
case .failure(let error):
}
so basically I tried to convert my JSON in dictionary by postJson.dictionaryObject. But always gets null from postJson.dictionaryObject (even though data is present in postJson).
I tried all combinations like postJson.dictionaryValue, postJson.dictionary, but no success.
I then tried to convert postJson to Data, and then dictionary:
if let data = postJson.data(using: .utf8) {
do {
return try JSONSerialization.jsonObject(with: data, options: []) as? [String: AnyObject]
}
catch {
print(error.localizedDescription)
}
}
and then post through Alamofire, now getting response. What am I doing wrong? I want to use my first option.

Assuming you are using Swift 3 / Alamofire 4.0
This is how you would define the "parameters" parameter according to Alamofire documentation:
let parameters: Parameters = ["foo": "bar"]
Alamofire.request(urlString, method: .get, parameters: parameters, encoding: JSONEncoding.default)
.downloadProgress(queue: DispatchQueue.global(qos: .utility)) { progress in
print("Progress: \(progress.fractionCompleted)")
}
.validate { request, response, data in
// Custom evaluation closure now includes data (allows you to parse data to dig out error messages if necessary)
return .success
}
.responseJSON { response in
debugPrint(response)
}
To learn more, click here

Related

Parse JSON when I get a error response in Alamofire

I've been working on API requests using Alamofire, and I want to know something for parsing the Error and to get the JSON data from the server instead of accessing the AFErrors. The code below works fine, but since I've been using .responseDecodable for decoding the response and also the MyError inherits Decodable, I was wondering if there is a similar way to decode data when I get the error response back, instead of using JSONDecoder().decode.
When I get the error response, it returns a JSON object with one value in it (message) from the server.
static let sessionManager: Session = {
let configuration = URLSessionConfiguration.af.default
configuration.timeoutIntervalForRequest = 30
return Session(configuration: configuration)
}()
Request.sessionManager.request(endpoint, method: httpMethod, parameters: params, headers: headers)
.responseDecodable(of: resDecodeType.self) { response in
switch response.result {
case .success(let successResponse):
completed(.success(successResponse))
case .failure(let error):
let errorStatusCode = response.response?.statusCode
do {
let data = try JSONDecoder().decode(MyError.self, from: response.data!) // -> this part...
} catch {
print(error)
}
}
}
}
struct MyError: Decodable {
let message: String
}

Alamofire 4, Swift 3 and building a json body

{"title":"exampleTitle","hashTags":[{"name":"tag1"},{"name":"tag2"}],"uploadFiles":
[{"fileBytes":"seriesOfBytes\n","filename":"upload.txt"}]}
That is my desired body I want to send to the backend.
I'm using Swift 3.0 and Alamofire 4 and i have multiple questions.
first, How do i correctly create a body which contains values and arrays of values?
My approach is:
let para:NSMutableDictionary = NSMutableDictionary()
para.setValue("exampleTitle", forKey: "title")
let jsonData = try! JSONSerialization.data(withJSONObject: para, options: .init(rawValue: 0))
let jsonString = NSString(data: jsonData, encoding: String.Encoding.utf8.rawValue) as! String
print(jsonString)
which gives me
{"title":"exampleTitle"}
second, my alamofire .post request looks like the following and is not working:
Alamofire.request(postURL, method: .post, parameters: jsonString, encoding: JSONEncoding.default)
.responseJSON { response in
debugPrint(response)
}
i get the error message: extra argument 'method' in call. If i instead of jsonString use a string of the type
var jsonString: [String : Any]
it does work, but i do not know how to put the body into this type.
summary
looking for help (example would be the best) on how to create the body, and how to send it via Alamofire 4 and swift 3 to my backend.
You need to pass parameter as [String:Any] dictionary, so create one dictionary as your passing JSON like this.
let params = [
"title":"exampleTitle",
"hashTags": [["name":"tag1"],["name":"tag2"]],
"uploadFiles":[["fileBytes":"seriesOfBytes\n","filename":"upload.txt"]]
]
Now pass this params as parameter in Alamofire request.
Alamofire.request(postURL, method: .post, parameters: params, encoding: JSONEncoding.default)
.responseJSON { response in
debugPrint(response)
}

How do I access a nested JSON value using Alamofire and SwiftyJSON?

I am trying to access nested JSON results using swiftyJSON and Alamofire. My print value is nill and I believe I am not doing this correctly. What should my parameters be? I am trying to get the quote value located at http://quotes.rest/qod.json
func getAPI() {
Alamofire.request(.GET, "http://quotes.rest/qod.json", parameters: ["contents": "quotes"])
.responseJSON { response in
if let JSON = response.result.value {
print(JSON["quote"])
}
}
}
In your JSON quotes is an array so if you want to access quote of the first object you should do it by accessing first object:
func getAPI() {
Alamofire.request(.GET, "http://quotes.rest/qod.json", parameters: ["contents": "quotes"])
.responseJSON { response in
if let jsonValue = response.result.value {
let json = JSON(jsonValue)
if let quote = json["contents"]["quotes"][0]["quote"].string{
print(quote)
}
}
}
}
If the syntax of the json isn't correct, since it is fully printed anyway you should notice what's wrong.
func getAPI() {
Alamofire.request(.GET, "http://quotes.rest/qod.json", parameters: ["contents": "quotes"])
// JSON response
.responseJSON { response in switch response.result {
case .Failure(let error):
// got an error in getting the data, need to handle it
print("error calling GET, json response type :")
// print alamofire error code
let statusCode = error.code
print("error code json : \(statusCode)")
// print json response from server
if let data = response.data {
print("Response data: \(NSString(data: data, encoding: NSUTF8StringEncoding)!)")
}
// print http status code plus error string
print(NSHTTPURLResponse.localizedStringForStatusCode(statusCode))
if let httpResponse : NSHTTPURLResponse = response.response {
print("HTTP Response statusCode: \(httpResponse.statusCode)")
}
case .Success( _):
let statusCode = (response.response?.statusCode)!
print("status code json : \(statusCode)")
print("there is a response json")
//print(value)
// parse the result as JSON, since that's what the API provides and save datas as new user in coreData
guard let data = response.data else {
print("Error parsing response data")
return
}
let json = JSON(data: data)
// access first element of the array
if let postContent = json["contents"]["quotes"][0]["quote"].string{
// deal with json
}
}
}

How does "let JSON" work in Alamofire/Swift

From here I see that the proper Alamofire 2/Swift 2 syntax when dealing with a JSON response is:
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)!)")
}
}
}
How and where is the let JSON defined? (From a Swift point of view.)
I see in a request extension that ResponseSerializer returns .Success(JSON) but why is the handler not defined like a usual function:
case .Success(JSON: AnyObject?) {
print("Success with JSON: \(JSON)")
}
or better yet:
case .Success(JSON: NSDictionary?) {
print("Success with NSDictionary: \(JSON)")
}
result is enum with cases .Success, .Failure. Enum cases in Swift can hold some value (by the way, that's how Optionals in Swift work, they are enums with two cases Some: which wraps a value and None). By calling case .Success(let JSON): in switch you assign this value to JSON constant and you can use it in case block. Type of this constant is automatically inferred.
For more information about it, check paragraph "Associated Values" in Swift Language Guide

How to convert <AnyObject> response in AnyObject after an Alamofire request with JSON in Swift?

So I want to send a request to a specific API which is supposed to return a JSON file.
I am using Alamofire in order to get the JSON object :
dataFromAPI : JSON
Alamofire.request(.GET, myURL).responseJSON { (_, _, data) -> Void in
dataFromAPI = JSON(data)
}
My problem is that data is an array of AnyObject and the JSON function needs an AnyObject type. How can I transform one into another or resolve the problem ?
Not sure if I got your question, but will try to provide you an example of how I do it.
Changed code to your case.
Alamofire.request(.GET, myURL)
.validate(statusCode: 200..<300)
.validate(contentType: ["application/json"])
.responseJSON { request, response, jsonResult in
switch jsonResult {
case .Success:
if let data = jsonResult.value as? AnyObject {
self.dataFromAPI = JSON(data)
}
case .Failure(_, let error):
print(error)
}
}
Normally I wouldn't do unwrapping to AnyObject, as it makes little sense.
I usually unwrap to [String: AnyObject] as I'm expecting Dictionary from my API, and then I attempt to convert it to my custom model class.
Correct me if I miss-understood the question. :)
Alamofire returns a Result<AnyObject> object. You should check if the result is a success or a failure before extracting the JSON:
Alamofire.request(.GET, myURL)
.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)!)")
}
}
}