Cannot update data in API using .PUT request in Alamofire - ios

I am creating an Event app where in the user should tap Check In Button to register for the event. registered_flag : false will be true and registered_type: 0 will be 1 once the user tapped the button. But as I build and run the app, error appeared that says
responseSerializationFailed(Alamofire.AFError.ResponseSerializationFailureReason.jsonSerializationFailed(Error
Domain=NSCocoaErrorDomain Code=3840 "Invalid value around character
0." UserInfo={NSDebugDescription=Invalid value around character 0.})).
I am not really confident regarding the content of my codes in my APIService. Hope someone will help me to correct my codes so I could build and run my app successfully. Thank you so much.
application/json that needs to be updated which inside event_participant
{
"registered_flag": false,
"registration_type": 0
}
event_participant
"event_participants": [
{
"participant_id": "70984656-92bc-4c36-9314-2c741f068523",
"employee_number": null,
"last_name": "Surname",
"first_name": "FirstName",
"middle_name": null,
"display_name": "Surname, FirstName ",
"department_name": "Department",
"position_name": "Developer",
"registered_flag": false,
"registered_datetime": "2018-09-13T08:54:40.150",
"registration_type": 0,
"delete_flag": false,
"manual_reg_flag": false,
"out_flag": false,
"out_datetime": null,
"classification": 6,
"others": "Guest"
}
}
API Service using PUT request in Alamofire
func updateParticipant(updateType: UpdateParticipantType,
participantID: String,
completionHandler: #escaping(([Attendee]?, Error?) -> Void)) {
let updateParticipantURL = URL(string: "\(REGISTER_PARTICIPANT_URL)/\(updateType)/\(participantID)")
let headers: HTTPHeaders = [
"Content-Type": "application/json"
]
let parameters: Parameters = [
"registered_flag": false,
"registration_type": 0
]
Alamofire.request(updateParticipantURL!, method: .put, parameters: parameters, encoding: JSONEncoding.default, headers: headers).responseJSON { (response) in
switch response.result {
case .success:
print("Done")
if let jsonArray = response.result.value as? [[String : Any]] {
for anItem in jsonArray {
if let eventparticipant = anItem["event_participants"] as? [[String : Any]] {
var extractedAttendee = [Attendee]()
for participant in eventparticipant{
print(participant)
let success = Attendee.init(JSON: participant)
extractedAttendee.append(success!)
}
completionHandler(extractedAttendee, nil)
}
}
}
case .failure(let error):
completionHandler(nil, error)
}
}
}
Struct for Attendee
struct Attendee: Decodable {
let id: String
let employeeNumber: String?
let lastName: String
let firstName: String
let middleName: String
let displayName: String
let department: String
let position: String
let registeredFlag: Bool
let registeredDateTime: Date?
let registrationType: Int
let deleteFlag: Bool
let manualFlag: Bool
let outFlag: Bool
let outDateTime: Date?
let classification: Int?
let others: String?
postman response

Related

How to parse json data include page number by codable in Swift 4 and Alamofire

I'm a new with Swift and I'm confusing to get data instead of using SwiftyJson by using Codable.
The format Json data type like as:
{
"current_page": 1,
"total_page": 407,
"new_entries": [
{
"id": 10174,
"title": "Hello",
"description": "Hello",
"categories": "women",
"image": "imagelink",
"url": "urllink",
"date": "time",
"is_favorite": false
},
{
"id": 9237,
"title": "hi",
"description": "hi",
"categories": "skincare",
"image": "imagelink",
"url": "url",
"date": "time",
"is_favorite": false
},
So how do I get the entries and decode and save to codable like
let decoder = JSONDecoder()
do {
let feed = try decoder.decode(Feed.self, from: jsonData)
print(feed.title)
} catch {
print(error.localizedDescription)
}
I stop at this below and dont know how to convert the json["new_entries"] to string type and decode.
Alamofire.request("https://abc.jp/api/category/women_all/?page=1", method: .get, parameters: nil, encoding: JSONEncoding.default, headers: nil).responseJSON { (response:DataResponse<Any>) in
debugPrint(response)
if let JSON = response.result.value as? NSDictionary {
GlobalVariables.sharedManager.pageCurr = JSON["current_page"] as? Int
GlobalVariables.sharedManager.pageTotal = JSON["total_page"] as? Int
if let entries = JSON["new_entries"] as? NSArray{
for entry in entries {
if let entry = entry as? NSDictionary {
for (key, value) in entry {
print("\(key) - \(value)")
}
}
}
}
}
My Feed Struct
struct Feed: Codable {
enum CodingKeys: String, CodingKey {
case id
case title
case description
case categories
case image
case url
case date
case favorite = "is_favorite"
}
let id: Int
let title: String
let description: String
let categories: String
let image: String
let url: String
let date: String
let favorite: Bool
}
Thanks so much.
You need
struct Root: Codable {
let currentPage, totalPage: Int
let newEntries: [Feed]
}
struct Feed: Codable {
let id: Int
let title, description, categories, image: String
let url, date: String
}
Alamofire.request("https://abc.jp/api/category/women_all/?page=1", method: .get, parameters: nil, encoding: JSONEncoding.default, headers: nil).responseData { response in
debugPrint(response)
guard let data = response.data else { return }
do {
let de = JSONDecoder()
de.keyDecodingStrategy = .convertFromSnakeCase
let res = try de.decode(Root.self, from: data)
print(res.currentPage)
print(res.totalPage)
print(res.newEntries)
}
catch {
print(error)
}
}
correct json
{
"current_page": 1,
"total_page": 407,
"new_entries": [
{
"id": 10174,
"title": "Hello",
"description": "Hello",
"categories": "women",
"image": "imagelink",
"url": "urllink",
"date": "time",
"is_favorite": false
},
{
"id": 9237,
"title": "hi",
"description": "hi",
"categories": "skincare",
"image": "imagelink",
"url": "url",
"date": "time",
"is_favorite": false
}]
}
I added a new main struct
struct Main: Codable {
let currentPage: Int
let totalPage: Int
let feeds: [Feed]
enum CodingKeys: String, CodingKey {
case currentPage = "current_page"
case totalPage = "total_page"
case feeds = "new_entries"
}
}
and then decode using that struct
let decoder = JSONDecoder()
do {
let result = try decoder.decode(Main.self, from: jsonData)
print(result.currentPage)
} catch {
print(error)
}
or with the alamofire example
Alamofire.request("https://abc.jp/api/category/women_all/?page=1", method: .get, parameters: nil, encoding: JSONEncoding.default, headers: nil).responseData { response in
guard let data = response.data else { return }
do {
let decoder = JSONDecoder()
let result = try decoder.decode(Main.self, from: data)
GlobalVariables.sharedManager.pageCurr = result.currentPage
GlobalVariables.sharedManager.pageTotal = result.totalPage
for feed in result.feeds {
print(feed.id)
//etc
}
} catch {
print(error)
// other error handling
}

How to parsed all the data in JSON?

First issue I addressed
I am working on an APIService using Alamofire, I tried to print the response and the I got the data successfully, but unfortunately the data from JSON turns to nil when I parse it to the attendees Object. How can I reflect the data from json to the attendees object?
Second Issue
I solved the 1st issue, after all the debugging I had. The codes I used was written in my answer below. I parsed data from JSON going to attendees but as I checked only the first array was fetch. How can I get all the data inside the JSON? Hope you can help me. Thank you.
func getParticipants(passcode: String,
participantType: ParticipantType,
successBlock: #escaping (Attendees?) -> Void,
failureBlock: #escaping (Error) -> Void)
{
let attendeesURL = URL(string: "\(GET_PARTICIPANTS_URL)/\(passcode)/\(participantType)")
Alamofire.request(attendeesURL!, method: .get).responseJSON { (response) in
print(response)
if let error = response.error
{
failureBlock(error)
return
}
if let attendeeJSON = response.result.value as? [Dictionary<String, Any>],
let attendeeObj = attendeeJSON.first {
print(attendeeObj)
let attendees = Attendees.init(JSON: attendeeObj)
successBlock(attendees)
}
}
}
}
JSON
[
{
"event_name": "Laugh Trip",
"event_participants": [
{
"participant_id": "6f1e7fd5-6da9-4d5b-bc91-4771aeaa5235",
"employee_number": "",
"last_name": "name",
"first_name": "name",
"middle_name": "",
"display_name": "name, name ",
"department_name": "IT",
"position_name": "Application Developer",
"registered_flag": true,
"registered_datetime": "2018-07-16T14:51:57.813",
"registration_type": 1,
"delete_flag": false,
"manual_reg_flag": false,
"out_flag": true,
"out_datetime": "2018-07-16T14:54:00.000",
"classification": 1,
"others": ""
},
{
"participant_id": "6f1e7fd5-6da9-4d5b-bc91-4771aeaa5235",
"employee_number": "",
"last_name": "name",
"first_name": "name",
"middle_name": "",
"display_name": "name, name ",
"department_name": "IT",
"position_name": "Application Developer",
"registered_flag": true,
"registered_datetime": "2018-07-16T14:51:57.813",
"registration_type": 1,
"delete_flag": false,
"manual_reg_flag": false,
"out_flag": true,
"out_datetime": "2018-07-16T14:54:00.000",
"classification": 1,
"others": ""
},
]
]
Instead of using first which gets only the first item of the sequence use a loop respectively.
if let events = response.result.value as? [[String : Any]] {
for event in events {
if let eventparticipants = event["event_participants"] as? [[String : Any]] {
print(eventparticipants)
for participant in eventparticipants {
let attendees = Attendees.init(JSON: participant)
successBlock(attendees)
}
}
}
}
I recommend to decode the JSON directly into structs with Decodable
I solved my own issue. :D
Alamofire.request(attendeesURL!, method: .get).responseJSON { (response) in
print(response)
if let error = response.error
{
failureBlock(error)
return
}
if let jsonDictionary = response.result.value as? [Dictionary<String, Any>]{
if let eventparticipants = jsonDictionary.first {
print(eventparticipants)
if let partObj = eventparticipants["event_participants"] as? [[String : Any]]{
let attendeeObj = partObj.first
let attendees = Attendees.init(JSON: attendeeObj!)
successBlock(attendees)
}
}
}
}

Using API in Swift (Postman,Alamofire,SwiftyJson)

I have an admin panel which admin can insert question and gives 3 options of answers to users to choose. The admin is able to insert questions according to different chapters...its like a quiz game..The correct answer is then given an int value so in my collection of 3 buttons, I am able to know which is the correct button user has chosen. But now my problem is, in my Postman:
in my swift code
func getaQuestionaByaChapter(chapterName: String,question: String, answer1: String, answer2 : String, answer3: String, answer: Int, completion: #escaping (JSON?, Error?) -> Void) {
let parameters: [String : Any] = [
"secret_key" : "b3370e1590a2cf2b430e8cf8a8b361bd",
"_action" : "GETQUESTIONBYCHAPTER",
"GETQUESTIONBYCHAPTER" : chapterName,
"question" : question,
"option1" : answer1,
"option2" : answer2,
"option3" : answer3,
"answer" : answer
]
is this a declaration correct?
as for my storyboard:
and after this, i would be doing
button1.setTitle = answer1
questionlabel.text = question
in my swift file for the part where i link my API
import SwiftyJSON
import Alamofire
public class EduappRestClient {
enum ContentType: String {
case json = "application/json"
case jpeg = "image/jpeg"
case formEncoded = "application/x-www-form-urlencoded"
case none = "" //Content type will be empty
}
private static let url: URL = URL(string: "http://192.168.0.127:81/project/Online_Question/API/actiona")! //NSURL depreciated now using URL)
//singleton
static let sharedClient: EduappRestClient = EduappRestClient()
class func request(with url: URL,
method: HTTPMethod = .get,
parameters: Parameters? = nil,
contentType: ContentType = .json,
encoding: ParameterEncoding = JSONEncoding.default,
additionalHeaders: [String: String] = [:],
completion: #escaping(JSON?, Error?) -> Void
) {
//MARK: Configure Headers
var headers: [String: String] = [:]
//if contenttype is specified as none type, leave content-type header field empty
if contentType != .none {
headers["Content-Type"] = contentType.rawValue
}
for (key, value) in additionalHeaders {
headers[key] = value
}
Alamofire.request(url, method: method, parameters: parameters, encoding: encoding, headers: headers).responseJSON(completionHandler: { (response) in
guard response.result.error == nil, let value = response.result.value else {
completion(nil, response.result.error)
return
}
let jsonData = JSON(value)
completion(jsonData, nil)
})
}
//MARK: - Getting questions by chapters
func getaQuestionaByaChapter(chapterName: String,question: String, answer1: String, answer2 : String, answer3: String, answer: Int, completion: #escaping (JSON?, Error?) -> Void) {
let parameters: [String : Any] = [
"secret_key" : "b3370e1590a2cf2b430e8cf8a8b361bd",
"_action" : "GETQUESTIONBYCHAPTER",
"GETQUESTIONBYCHAPTER" : chapterName,
"question" : question,
"option1" : answer1,
"option2" : answer2,
"option3" : answer3,
"answer" : answer
]
let URLString = EduappRestClient.url
EduappRestClient.request(with: URLString, method: .post, parameters: parameters) { (json, error) in
guard error == nil, let json = json else {
completion(nil, error)
return
}
let result: JSON = json[1]
//result will print
//"question": [
// {
//"question": "10+10",
//"chapter_name": "Chapter 2",
//"option1": "10",
//"option2": "20",
//"option3": "30",
//"answer": "20"
//}
//]
completion(result, nil)
}
}}
it will show my data accordingly??
After API response, you have to use.
class QuestionModel: Codable {
let questions: [Details]
}
class Details: Codable {
let question: String?
let chapter_name: String?
let option1: Int?
let option2: Int?
let option3: Int?
}
And after this, you have to parse the response in the model data:
func getaQuestionaByaChapter(chapterName: String, completion: #escaping (QuestionModel?, Error?) -> Void) {
let parameters: [String : Any] = [
"secret_key" : "b3370e1590a2cf2b430e8cf8a8b361bd",
"_action" : "GETQUESTIONBYCHAPTER",
"GETQUESTIONBYCHAPTER" : chapterName
]
let URLString = EduappRestClient.url
EduappRestClient.request(with: URLString, method: .post, parameters: parameters) { (json, error) in
guard error == nil, let json = json else {
completion(nil, error)
return
}
do {
let jsonData = try JSONSerialization.data(withJSONObject: json, options: JSONSerialization.WritingOptions.prettyPrinted)
let result = try JSONDecoder().decode(QuestionModel.self, from: jsonData)
completion(result, nil)
} catch let message {
print("JSON serialization error:" + "\(message)")
}
}
}}
Then in QuizViewController: You have to set the data:
EduappRestClient.sharedClient.getaQuestionaByaChapter(chapterName: "Chapter 2", completion: { (response, error) in
//json is the result from rest client
let firstQuestion = response?.questions.first
self.questionsLabel.text = firstQuestion?.question
self.answerButtons.setTitle("\(firstQuestion?.option1)", for: UIControlState.normal)
self.answerButtons.setTitle("\(firstQuestion?.option2)", for: UIControlState.normal)
self.answerButtons.setTitle("\(firstQuestion?.option3)", for: UIControlState.normal)
})

Alamofire .post api error: Code=3840 "Invalid value around character 1

Using Alamofire for .post api, api giving data in postman but not in my code. Posting below the code, please guide what wrong i am doing here:
// API calling method:
parameters = [
"Address" : "" as AnyObject,
"Name" : "" as AnyObject,
"ServiceID" : "" as AnyObject,
"Rating" : "" as AnyObject,
"Price" : "" as AnyObject
]
let headers: Dictionary = [
"" : ""
]
print(parameters)
ApiServices.requestPOSTURL(strURL, params: parameters, headers: headers, success:{
(JSONResponse) -> Void in
CommonMethodsClass.hideHUD(targetView: self.view)
print(JSONResponse["message"])
let strMsg = JSONResponse["message"].stringValue
if (JSONResponse["status"].intValue == 1)
{
}
else
{
CommonMethodsClass.showAlertMessage(vc: self, titleStr: "Error!", messageStr: strMsg)
}
}) {
(error) -> Void in
print(error)
CommonMethodsClass.hideHUD(targetView: self.view)
}
// Api request method:
class func requestPOSTURL(_ strURL : String, params : [String : AnyObject]?, headers : [String : String]?, success:#escaping (JSON) -> Void, failure:#escaping (Error) -> Void){
Alamofire.request(strURL, method: .post, parameters: params, encoding: JSONEncoding.default).responseJSON { (responseObject) -> Void in
print(responseObject)
if responseObject.result.isSuccess {
let resJson = JSON(responseObject.result.value as Any)
success(resJson)
}
if responseObject.result.isFailure {
let error : Error = responseObject.result.error!
failure(error)
}
}
}
Error: FAILURE:
responseSerializationFailed(Alamofire.AFError.ResponseSerializationFailureReason.jsonSerializationFailed(Error
Domain=NSCocoaErrorDomain Code=3840 "Invalid value around character
1." UserInfo={NSDebugDescription=Invalid value around character 1.}))
Update: Response to parse, may also needs to be changed.
{
"status": true,
"message": "",
"data": [
{
"SalonID": "1",
"SalonName": "Affinity",
"SalonEmail": "vay.chaan#th-rce.com",
"SalonPhone": "9999888877",
"SalonMobile": "9999888877",
"SalonAddress": "C-28, Sec-58, India",
"Latitude": "18.5806",
"Longitude": "27.36273",
"Image": null,
"SalonImage": "",
"TimeIntervalminutes": 20,
"AverageRating": 4,
"IsActive": 1
},
{
"SalonID": "3",
"SalonName": "Looks",
"SalonEmail": "rad#th-rce.com",
"SalonPhone": "99998828877",
"SalonMobile": "99998388877",
"SalonAddress": "GP Mall,India",
"Latitude": "",
"Longitude": "",
"Image": null,
"SalonImage": "",
"TimeIntervalminutes": 30,
"AverageRating": 5,
"IsActive": 1
}
]
}
Replace responseJSON with responseString.
You need to convert the string for values. Can you update the string in your question?
You can use this function to convert response string into JSON:
func convertToDictionary(text: String) -> [String: Any]? {
if let data = text.data(using: .utf8) {
do {
return try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]
} catch {
print(error.localizedDescription)
}
}
return nil
}
String: let str = "{\"name\":\"James\"}"
USAGE: let dict = convertToDictionary(text: str)
Try responseString instead of responseJSON and it will work
Alamofire.request("URL").responseString { response in
print(response)
if let json = response.result.value {
print("JSON: \(json)")
}
}
Change responseJSON to responseString and it will work :)
Alamofire.request("URL").responseString { response in
print(response)
if let json = response.result.value {
print("JSON: \(json)")
}
}

Swift Alamofire Request Error - Extra Argument in call

I am getting an error when I am trying to request using Alamofire. The error says that there is an 'extra argument in call'.
class SwiftStockKit {
class func fetchStocksFromSearchTerm(term: String, completion:#escaping (_ stockInfoArray: [StockSearchResult]) -> ()) {
DispatchQueue.global(priority: DispatchQueue.GlobalQueuePriority.default).async {
let searchURL = "http://autoc.finance.yahoo.com/autoc"
Alamofire.request(.GET, searchURL, parameters: ["query": term, "region": 2, "lang": "en"]).responseJSON { response in
if let resultJSON = response.result.value as? [String : AnyObject] {
if let jsonArray = (resultJSON["ResultSet"] as! [String : AnyObject])["Result"] as? [[String : String]] {
var stockInfoArray = [StockSearchResult]()
for dictionary in jsonArray {
stockInfoArray.append(StockSearchResult(symbol: dictionary["symbol"], name: dictionary["name"], exchange: dictionary["exchDisp"], assetType: dictionary["typeDisp"]))
}
dispatch_async(dispatch_get_main_queue()) {
completion(stockInfoArray: stockInfoArray)
}
}
}
}
}
}
The line that is giving me an error is:
Alamofire.request(.GET, searchURL, parameters: ["query": term, "region": 2, "lang": "en"]).responseJSON { response in
if anyone could fix this I would be really grateful, thanks
Try change your request to something like this:
Alamofire.request(searchURL, method: .get, parameters: ["query": term, "region": 2, "lang": "en"], encoding: JSONEncoding.default, headers: nil)

Resources