The API i have is a post method and response in postman is as follows:
Post Url : https://xxxxxx/xxxxxxxx/public/api/chatrequest
Body params:property_id:40 , identity:demo Header: x-token and content type
The response is as follows:
{
"Token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImN0eSI6InR3aWxpby1mcGE7dj0xIn0.eyJqdGkiOiJTS2E4ZGNjNTRlZTkwODYyNDcyNWRiN2Q4ODlhZjY3YTJkLTE1ODY2MjAyMDIiLCJpc3MiOiJTS2E4ZGNjNTRlZTkwODYyNDcyNWRiN2Q4ODlhZjY3YTJkIiwic3ViIjoiQUNjNTllMWMzN2ZmZjdiZmIyYTIxMzkyOGY3NTdjMzhkYyIsImV4cCI6MTU4NjYyMzgwMiwiZ3JhbnRzIjp7ImlkZW50aXR5IjoiMTciLCJjaGF0Ijp7InNlcnZpY2Vfc2lkIjoiSVMxODQ1Mzg5ZDhmYjE0N2M4OTU2Zjg5ZmM0MTk1ODdkYSJ9fX0.FeLxlmdYr8WglNs_2vH0qYGbeRJ9vaVoWIVE8qTn6hA",
"identity": 17,
"ChannelID": "jNqNLaUS2mUg1TRqMVPua5ghcFDpBSUI",
"ChannelSid": "CHb24932d10fe34bca82153c87ba18edc1",
"ChannelData": {
"id": 76,
"propertys_id": "40",
"from_user": "17",
"to_user": "18",
"channel": "jNqNLaUS2mUg1TRqMVPua5ghcFDpBSUI",
"sid": "CHb24932d10fe34bca82153c87ba18edc1",
"from_token": "MB368a9a6ea1e64078abaa98b61952eb25",
"to_token": "MB15aea3092366476e8ab437d303fbdab5",
"created_at": "2020-04-10 17:01:52",
"updated_at": "2020-04-10 17:01:52"
}
}
The code used to fetch this response is as follows:
fetchToken(params: ["property_id":"21"]) {response,error in
var token: String?
token = response["token"] as? String
var clientsid: String?
clientsid = response["ChannelSid"] as? String
completion(token != nil, token,clientsid)
}
func fetchToken(params:[String:String], completion:#escaping (NSDictionary, NSError?) -> Void) {
var request = URLRequest(url: URL(string: "https://reachwebdemo.com/listcrib/public/api/chatrequest")!)
request.httpMethod = "POST"
let postString = postDataFrom(params: params)
print("poststring is",postString)
request.httpBody = postString.data(using: .utf8)
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue(self.usertoken, forHTTPHeaderField: "x-token")
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else {
print("error=\(String(describing: error))")
completion(NSDictionary(), error as NSError?)
return
}
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {
completion(NSDictionary(), NSError(domain: "TWILIO", code: 1000, userInfo: [NSLocalizedDescriptionKey: "Incorrect return code for token request."]))
return
}
do {
let json = try JSONSerialization.jsonObject(with: data, options: []) as! [String:Any]
print("json response = \(json)")
completion(json as NSDictionary, error as NSError?)
} catch let error as NSError {
completion(NSDictionary(), error)
}
}
task.resume()
}
else {
let userInfo = [NSLocalizedDescriptionKey : "TokenRequestUrl Key is missing"]
let error = NSError(domain: "app", code: 404, userInfo: userInfo)
completion(NSDictionary(), error)
}
}
The response i get from the code is as follows:
json response = ["errors": <__NSSingleObjectArrayI 0x600003faebf0>(
The property id field is required.
)
]
What is the issue with the code?Why is the response is not fetched properly same as postman?
Related
I'm trying to decode a JSON I get from a server. But I always get this error:
The data couldn’t be read because it is missing.
I don't understand why I get this error, I looked and saw few answers but nothing solved my problem, I can't figure it out.
This is the response I get from the server (as shown in Postman):
{
"email": "new#user.com",
"username": "newuser",
"user_rating": 0,
"store_id": "",
"state": "",
"city": "",
"address": "",
"zip_code": 0,
"user_id": "user_id_test",
"created_on": 1585933800
}
This is my Swift code:
func getUser(id: String, completion: #escaping(User?, Error?) -> Void) {
let urlParams = "/?id=\(id)"
guard let url = URL(string: baseURL + "getUser" + urlParams) else { return }
var request = URLRequest(url: url)
request.httpMethod = "GET"
_ = URLSession.shared.dataTask(with: request, completionHandler: { (data, response, error) in
if let error = error {
completion(nil, error)
debugPrint(error) //TODO: Handle error.
return
}
guard let jsonData = data else { return }
print(String(bytes: jsonData, encoding: .utf8))
do {
let user = try self.decoder.decode(User.self, from: jsonData)
completion(user, nil)
} catch { print(error.localizedDescription) }
}).resume()
}
This line: print(String(bytes: jsonData, encoding: .utf8)) prints:
Optional("{\"email\":\"new#user.com\",\"username\":\"newuser\",\"user_rating\":0,\"store_id\":\"\",\"state\":\"\",\"city\":\"\",\"address\":\"\",\"zip_code\":0,\"user_id\":\"user_id_test\",\"created_on\":1585933800}")
Which looks okay to me.
This is the User Struct I'm trying to decode:
struct User: Codable {
let email: String!
let username: String!
let rating: Float!
let storeID: String?
let state: String?
let city: String?
let address: String?
let zipCode: Int
let uuid: String!
let createdOn: TimeInterval!
}
I'm trying to update an attribute via PUT request using JSONSerialization.
Here is my function :
func updateRGPDStatus(user:UserModel){
let parameters = ["firstname": user.firsname as Any,
"lastname": user.lastname as Any,
"mail": user.mail as Any,
"has_web_access": user.has_web_access as Any,
"has_mobile_access": user.has_mobile_access as Any,
"id_user": user.id_user as Any,
"has_accepted_rgpd": user.rgpd as Any
] as [String : Any]
guard let url = URL(string: UPDATE_RGPD_STATUS) else { return }
var request = URLRequest(url: url)
request.httpMethod = "PUT"
guard let httpBody = try? JSONSerialization.data(withJSONObject: parameters, options: []) else {
return
}
request.httpBody = httpBody
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
let session = URLSession.shared
session.dataTask(with: request) { (data, response, error) in
if let response = response {
print(response)
}
if let data = data {
do {
let json = try JSONSerialization.jsonObject(with: data, options: [])
print(json)
}
catch {
print(error)
}
}
}.resume()
}
and here is the json that I'm supposed to update :
{
"user": {
"firstname": "first_name",
"lastname": "last_name",
"mail": "validEmail#mail.com",
"has_web_access": true,
"has_mobile_access": true,
"id_user": 17,
"has_accepted_rgpd": false
}
}
When I send my request, I got and error of type "missing parameters" because I don't include the "user" attribute in my request which I don't know how to do it at this stage of my learning. Any help please. Thank you ^^
You can try
let res:[String : Any] = ["firstname": user.firsname as Any,
"lastname": user.lastname as Any,
"mail": user.mail as Any,
"has_web_access": user.has_web_access as Any,
"has_mobile_access": user.has_mobile_access as Any,
"id_user": user.id_user as Any,
"has_accepted_rgpd": user.rgpd as Any
]
let parameters:[String : Any] = ["user":res] // the new parameters
I have recently worked with the http put method i sent parameters like this
let param = [
"quantity" : quantity!
] as [String : Any]
And this worked for me.
How to fix this error?
Cannot convert value of type '(ApiContainer, ) -> ()' to
expected argument type '(ApiContainer<>?, Error?) -> ()
Screenshot showing the error
JSON response from the server:
{
"meta": {
"sucess": "yes",
"value": "123"
},
"result": [
{
"name": "Name 1",
"postal_code": "PC1",
"city": "City 1",
"address": "01 Street"
},
{
"name": "Name 2",
"postal_code": "PC2",
"city": "City 2",
"address": "02 Street"
}
]
}
Structs
struct Client: Decodable {
let name: String
let postal_code: String
let city: String
}
struct Meta: Decodable {
let sucess: String
let value: String
}
struct ApiContainer<T: Decodable>: Decodable
let meta: Meta
let result: [T]
}
I have a function 'getAll' that is supposed to make a request and return the correspondent struct (ApiContainer where T can be for example Client)
func getAll() {
makeRequest(endpoint: "http://blog.local:4711/api/all", completionHandler:
{(response: ApiContainer<Client>, error) in
if let error = error {
print("error calling POST on /todos")
print(error)
return
}
print(result)
//self.tableArray = decodedData.result
DispatchQueue.main.async {
self.tableView.reloadData()
}
} )
}
Function makeRequest is called from getAll()
func makeRequest<T>(endpoint: String, completionHandler: #escaping (ApiContainer<T>?, Error?) -> ()) {
guard let url = URL(string: endpoint) else {
print("Error: cannot create URL")
let error = BackendError.urlError(reason: "Could not create URL")
completionHandler(nil, error)
return
}
let urlRequest = URLRequest(url: url)
let session = URLSession.shared
let task = session.dataTask(with: urlRequest, completionHandler: {
(data, response, error) in
guard let responseData = data else {
print("Error: did not receive data")
completionHandler(nil, error)
return
}
guard error == nil else {
completionHandler(nil, error!)
return
}
do {
let response = try JSONDecoder().decode(ApiContainer<T>.self, from: responseData)
completionHandler(response, nil)
}
catch {
print("error trying to convert data to JSON")
print(error)
completionHandler(nil, error)
}
})
task.resume()
}
In case of generics you have to annotate the types in the closure explicitly to specify the static type of the generics
makeRequest(endpoint: "http://blog.local:4711/api/all",
completionHandler: { (container : ApiContainer<Client>?, error : Error?) in ...
I have an issue with loading JSON results within swift (php connection).
I can retrieve JSON data but it will not let me assign it to a variable.
it always assigns the results as Optional.
The JSON Data:
{
"country": [{
"id": 1,
"name": "Australia",
"code": 61
}, {
"id": 2,
"name": "New Zealand",
"code": 64
}]
}
The xCode Output:
["country": <__NSArrayI 0x60000002da20>(
{
code = 61;
id = 1;
name = Australia;
},
{
code = 64;
id = 2;
name = "New Zealand";
}
)
]
Country Name: Optional(Australia)
Country Name: Optional(New Zealand)
The .swift file:
//function did_load
override func viewDidLoad() {
super.viewDidLoad()
//created RequestURL
let requestURL = URL(string: get_codes)
//creating NSMutable
let request = NSMutableURLRequest(url: requestURL!)
//setting the method to GET
request.httpMethod = "GET"
//create a task to get results
let task = URLSession.shared.dataTask(with: request as URLRequest) {
data, response, error in
if error != nil{
print("error is \(String(describing: error))")
return;
}
//lets parse the response
do {
let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as! [String: Any]
print(json)
if let countries = json["country"] as? [[String: AnyObject]] {
for country in countries {
print("Country Name: \(String(describing: country["name"]))")
print("Country Code: \(String(describing: country["code"]))")
if let couname = country["name"] as? [AnyObject] {
print(couname)
}
if let coucode = country["code"] as? [AnyObject] {
print(coucode)
}
}
}
} catch {
print("Error Serializing JSON: \(error)")
}
}
//executing the task
task.resume()
}
You need to unwrap the optional before you try to use it via string interpolation. The safest way to do that is via optional binding:
Please use below code, which will work for you.
if let countries = json["country"] as? [[String: AnyObject]] {
for country in countries {
print("Country Name: \(country["name"] as! String)")
print("Country Code: \(country["code"] as! String)")
if let couname = country["name"] as? String {
print(couname)
}
if let coucode = country["code"] as? Int {
print(coucode)
}
}
}
I am new in Swift and iOS. Please send me the sample code for POST request with JSON data to external database for login app in iOS using Swift
You can call post api like below code,
Try this
func callPostApi()
{
let baseUrl : NSString = NSString(format: "YOUR_BASE_URL") //"http://at.webby.com/php.api"
let request = NSMutableURLRequest(URL: NSURL(string: baseUrl as String)!)
let session = NSURLSession.sharedSession()
request.HTTPMethod = "POST"
let stringPost = "username=test&password=12345" // Key and Value param as string
let data = stringPost.dataUsingEncoding(NSUTF8StringEncoding)
request.timeoutInterval = 60
request.HTTPBody=data
let task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
let err1: NSError? = nil
do
{
let json = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers)
print(json)
}
catch
{
print(err1)
}
})
task.resume()
}
Hope this will help you.
class ViewController: UIViewController {
#IBOutlet weak var tblView: UITableView!
var arrData = NSArray()
override func viewDidLoad() {
super.viewDidLoad()
postAPICall()
}
func postAPICall() {
let urlString = "http://18.220.215.90/backend/web/index.php/site/getstylistlist"
let dictParameter = ["Salon_Latitude": "23.0387822",
"Register_User_ID": "0",
"page": "0",
"Filter_Keyword": "",
"Register_User_Year_Of_Experience": "0",
"Salon_Longitude": "72.514567",
"pagesize": "20",
"api_type": "iphone",
"Register_User_Login_ID": "0",
"Cost": "0",
"Version": "1",
"api_userid": "",
"Distance_KM": "",
"Register_User_Professional_Sub_Type": "All"
]
let param = JsonStringFromDictionary(parameter: dictParameter as AnyObject, type: "json")
Alamofire.request(urlString, method: .post, parameters: param, encoding: URLEncoding.httpBody, headers: nil).responseJSON { (response:DataResponse!) in
switch response.result{
case.success:
print("Sucess")
if let JSON = response.result.value {
self.arrData = JSON as! NSArray
print(self.arrData)
}
case.failure(let Error):
print("error\(Error)")
}
}
}