How to add Array value to JSON Key in Swift - json

How to add request.httpBody = getPostData(params: ["contactsList": ["1212121212, "5555555544"]]) in place of
let parameters = getPostString(params: ["contactsList":[phNumArray]])
below is working code but how to add phNumArray in palce of individual of individual numberes to contactsList
Postman output for API:
working code: anyone can copy paste to see output
import UIKit
class TestViewController: UIViewController {
var phNumArray = ["1111111111", "5555555544"]
override func viewDidLoad() {
super.viewDidLoad()
callPostApi()
}
func getPostString(params: [String: Any]) -> String {
var data = [String]()
for (key, value) in params {
data.append(key + "=\(value)")
}
print(data.map { String($0) }.joined(separator: "&"))
return data.map { String($0) }.joined(separator: "&")
}
func callPostApi() {
let url = URL(string: "http://itaag-env-1.ap-south-1.elasticbeanstalk.com/filter/taggedusers/")
guard let requestUrl = url else { fatalError() }
var request = URLRequest(url: requestUrl)
request.httpMethod = "POST"
request.setValue("EC3746E9-4DB4-42C7-9D8C-1542B18C2AC", forHTTPHeaderField: "deviceid")
request.setValue("5fe42fb3b54543a0bab5667cf96526f8", forHTTPHeaderField: "key")
request.setValue("personal", forHTTPHeaderField: "userType")
let parameters = getPostString(params: ["contactsList": ["5555555544", "11111111111"]])
print("json parameter phone numbers \(parameters)")
request.httpBody = parameters.data(using: .utf8)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
let httpResponse = response as? HTTPURLResponse
// Check for Error
if let error = error {
print("Error took place \(error)")
return
}
if let data = data, let dataString = String(data: data, encoding: .utf8) {
print("Response data string:\n \(dataString)")
do {
let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as! [String: Any]
print("fetching json \(json)")
let fetchStatus = json["userName"] as? String
print("fetching json userName \(String(describing: fetchStatus))")
let user = json["5555555544"] as? [String: Any]
let name = user?["userName"] as? String
print("first username \(name)")
} catch {}
}
}
task.resume()
}
}
please help me to solve the issue with contactsList value.

Update: All this time you were sending the request as JSON encoded instead of as form-data. I'm adding the code for that below, try it out:
class ViewController: UIViewController {
var phNumArray = ["1111111111", "5555555544"]
override func viewDidLoad() {
super.viewDidLoad()
callPostApi()
}
func getPostData(params: [String:Any]) -> Data? {
return try? JSONSerialization.data(withJSONObject: params, options: .prettyPrinted)
}
func callPostApi() {
let url = URL(string: "http://itaag-env-1.ap-south-1.elasticbeanstalk.com/filter/taggedusers/")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("EC3746E9-4DB4-42C7-9D8C-1542B18C2AC", forHTTPHeaderField: "deviceid")
request.setValue("5fe42fb3b54543a0bab5667cf96526f8", forHTTPHeaderField: "key")
request.setValue("personal", forHTTPHeaderField: "userType")
try? request.setMultipartFormData(["contactsList": "\(phNumArray)"], encoding: .utf8)
URLSession.shared.dataTask(with: request) { data, _, _ in
if let data = data, let json = try? JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String: Any] {
let user = json["5555555544"] as? [String: Any]
let name = user?["userName"] as? String
print("first username \(name)")
}
}.resume()
}
}
extension URLRequest {
public mutating func setMultipartFormData(_ parameters: [String: String], encoding: String.Encoding) throws {
let makeRandom = { UInt32.random(in: (.min)...(.max)) }
let boundary = String(format: "------------------------%08X%08X", makeRandom(), makeRandom())
let contentType: String = try {
guard let charset = CFStringConvertEncodingToIANACharSetName(CFStringConvertNSStringEncodingToEncoding(encoding.rawValue)) else {
throw MultipartFormDataEncodingError.characterSetName
}
return "multipart/form-data; charset=\(charset); boundary=\(boundary)"
}()
addValue(contentType, forHTTPHeaderField: "Content-Type")
httpBody = try {
var body = Data()
for (rawName, rawValue) in parameters {
if !body.isEmpty {
body.append("\r\n".data(using: .utf8)!)
}
body.append("--\(boundary)\r\n".data(using: .utf8)!)
guard
rawName.canBeConverted(to: encoding),
let disposition = "Content-Disposition: form-data; name=\"\(rawName)\"\r\n".data(using: encoding) else {
throw MultipartFormDataEncodingError.name(rawName)
}
body.append(disposition)
body.append("\r\n".data(using: .utf8)!)
guard let value = rawValue.data(using: encoding) else {
throw MultipartFormDataEncodingError.value(rawValue, name: rawName)
}
body.append(value)
}
body.append("\r\n--\(boundary)--\r\n".data(using: .utf8)!)
return body
}()
}
}
public enum MultipartFormDataEncodingError: Error {
case characterSetName
case name(String)
case value(String, name: String)
}
Instead of converting to JSON String and then converting it to Data, use JSONSerialization, here's an example:
func getPostData(params:[String:Any]) -> Data? {
return try? JSONSerialization.data(withJSONObject: params, options: .prettyPrinted)
}
And then assign it directly to URLRequest's httpBody, like this:
let arrayOfNumbers = [String]()
arrayOfNumbers.append("5555555544")
arrayOfNumbers.append("11111111111")
request.httpBody = getPostData(params: ["contactsList": arrayOfNumbers])
Also, go through the Apple Documentation, you'll find valuable information there. If don't understand concepts there google more about JSONSerializing and POST request httpBody.

Related

Passing data to the next POST request from that was fetched in the previous one [Swift / SwiftUI]

I am looking for a way how to pass further data that was received in the previous POST request. Below is my code.
Actual result: authtoken and sms_id become an empty String.
Some clarifications: The second POST request is called in the next screen in the sequence when the first is completed. TIA.
import SwiftUI
import Combine
enum APIError: Error {
case responseProblem
case decodingProblem
case encodingProblem
}
class NetworkService: ObservableObject {
#Published var user: UserRegisterRequest?
#Published var userRegistered: UserRegistered?
let uuid = UIDevice.current.identifierForVendor?.uuidString
let appid = "com.website.me"
var authToken = ""
var sms_id = ""
func postPhoneValidation(_ phone: String, completion: #escaping (Result<UserRegisterRequest, APIError>) -> Void) {
do {
guard let url = URL(string: APIRequests.postPhoneValidation) else { fatalError() }
let body: [String: Any] = ["phone" : phone]
let finalBody = try JSONSerialization.data(withJSONObject: body)
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = finalBody
request.setValue(uuid, forHTTPHeaderField: "X-AUTH-Device")
request.setValue(appid, forHTTPHeaderField: "X-AUTH-AppID")
URLSession.shared.dataTask(with: request) { data, response, _ in
guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200,
let jsondata = data else {
completion(.failure(.responseProblem))
return
}
do {
let validatedPhoneDictionary = try JSONDecoder().decode(UserRegisterRequest.self, from: jsondata)
self.authToken = validatedPhoneDictionary.auth_token
self.sms_id = validatedPhoneDictionary.sms_id
completion(.success(validatedPhoneDictionary))
print(validatedPhoneDictionary)
} catch {
completion(.failure(.decodingProblem))
}
}
.resume()
} catch {
completion(.failure(.encodingProblem))
}
}
func postSignUp(_ otpSms: String, completion: #escaping (Result<UserRegistered, APIError>) -> Void) {
do {
guard let url = URL(string: APIRequests.postSignUp) else { fatalError() }
let body : [String: Any] = ["otpSms" : otpSms, "sms_id" : self.sms_id]
let finalBody = try! JSONSerialization.data(withJSONObject: body)
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = finalBody
request.setValue(uuid, forHTTPHeaderField: "X-AUTH-Device")
request.setValue(appid, forHTTPHeaderField: "X-AUTH-AppID")
request.setValue(self.authToken, forHTTPHeaderField: "X-AUTH-Token")
URLSession.shared.dataTask(with: request) { data, response, _ in
guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200,
let jsondata = data else {
completion(.failure(.responseProblem))
return
}
do {
let registeredUser = try JSONDecoder().decode(UserRegistered.self, from: jsondata)
completion(.success(registeredUser))
print(registeredUser)
} catch {
completion(.failure(.decodingProblem))
}
}
.resume()
}
}
}
The reason for my problem was the moment that in view where I call the second method I've created a new instance of NetworkService instead of access it as ObservedObject. When I've changed it the problem was solved. –

i am trying to parse json with swift 4, please tell me what is wrong in it?

I am trying to parse JSON using the following method, but XCode is giving me an error where I have declared "data" .
I am new, I don't understand what is wrong. Please help me.
import UIKit
struct Contacts: Decodable {
let id: Int
let name: String
let email: String
}
class ViewController: UIViewController {
override func viewDidLoad()
{
super.viewDidLoad()
let urlString = "https://api.androidhive.info/contacts/"
guard let url = URL(string: urlString) else {return}
URLSession.shared.dataTask(with: url) { (data, response, error) in
}
guard let data = data else {return}
//let datastring = String(data: data, encoding: .utf8)
do
{
let contact = try JSONDecoder().decode([Contacts].self, from: data)
print(contact.name)
} catch let jsonErr {
print("Error deserializing json:", jsonErr)
}
}
}
Three major issues.
You are ignoring the root object which is a dictionary containing the contacts array.
The value for key id is String, not Int.
A hard rule is : Everything in double quotes is String even "12" and "false"
You have to resume the task and put the code to parse the JSON into the completion handler.
struct Root : Decodable {
let contacts : [Contact]
}
struct Contact : Decodable { // It's recommended to name this kind of struct in singular form
let id, name, email: String
}
...
override func viewDidLoad()
{
super.viewDidLoad()
let urlString = "https://api.androidhive.info/contacts/"
guard let url = URL(string: urlString) else {return}
URLSession.shared.dataTask(with: url) { (data, response, error) in
if let error = error { print(error); return }
do {
let result = try JSONDecoder().decode(Root.self, from: data!)
let contacts = result.contacts
for contact in contacts {
print(contact.name)
}
} catch {
print("Error deserializing json:", error)
}
}.resume()
}
//
// ViewController.swift
// PostMethodTest
//
// Created by HABIB UR REHMAN on 12/11/2018.
// Copyright © 2018 HABIB UR REHMAN. All rights reserved.
//
import UIKit
class ViewController: UIViewController {
struct Resturant: Decodable {
var name: String
var deliveryCharges: String
var email: String
init(_ dictionary: [String: Any]) {
self.name = dictionary["name"] as? String ?? ""
self.deliveryCharges = dictionary["deliveryCharges"] as? String ?? ""
self.email = dictionary["email"] as? String ?? ""
}
}
override func viewDidLoad() {
super.viewDidLoad()
guard let url = URL(string: "your Link Here ") else { return }
var request = URLRequest(url: url)
request.httpMethod = "POST"
let task = URLSession.shared.dataTask(with: request) {(data, response, error) in
guard let dataResponse = data,
error == nil else {
print(error?.localizedDescription ?? "Response Error")
return }
do{
//here dataResponse received from a network request
let jsonResponse = try JSONSerialization.jsonObject(with:
dataResponse, options: [])
print(jsonResponse) //Response result
} catch let parsingError {
print("Error", parsingError)
}
}
task.resume()
}
}
Please Try this its working for me.
func getContactListsApiCalling() {
var request = URLRequest(url: URL(string: "https://api.androidhive.info/contacts/")!)
request.httpMethod = "GET"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
let session = URLSession.shared
let task = session.dataTask(with: request, completionHandler: { data, response, error -> Void in
do {
if let Data = data {
let responseJSON = try JSONSerialization.jsonObject(with: Data) as? Dictionary<String, AnyObject> ?? [:]
if let contacts = responseJSON["contacts"] as? [[String :AnyObject]] {
for contact in contacts {
let id = contact["id"] as? String ?? ""
let name = contact["name"] as? String ?? ""
let email = contact["email"] as? String ?? ""
let address = contact["address"] as? String ?? ""
let gender = contact["gender"] as? String ?? ""
print(id,name,email,address,gender)
}
}
}
} catch {
print("error")
}
})
task.resume()
}
}

Unable to upload an image using Swift

I am unable to upload an image using swift. All the other information is inserted correctly into the database. This function submit book details but it also needs to submit an image. How do I submit an image using my current swift code? Thanks.
func uploadOrder (completion: #escaping (Bool, Any?, Error?) -> Void) {
let imageSize: CGSize = (self._book.imageView?.bounds.size)!
UIGraphicsBeginImageContextWithOptions(imageSize, false, 0)
let context = UIGraphicsGetCurrentContext()
self._book.imageView?.layer .render(in: context!)
let myImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
let imageData: NSData = UIImageJPEGRepresentation(myImage, 90)! as NSData
UIGraphicsEndImageContext()
let jsonDictionary = NSMutableDictionary()
guard let url = URL(string: Constants.uploadOrder) else { return }
var urlRequest = URLRequest(url: url)
urlRequest.httpMethod = "POST"
urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
if let isbn = self._book.ISBN as String? {
jsonDictionary.setValue(isbn, forKey:"isbn")
} else {
jsonDictionary.setValue("", forKey:"isbn")
}
guard let httpBody = try? JSONSerialization.data(withJSONObject: jsonDictionary, options: []) else {
return
}
urlRequest.httpBody = httpBody
let session = URLSession.shared
session.dataTask(with: urlRequest) { (data, response, error) in
if let response = response {
print("Response", response)
}
if let data = data {
do {
let json = try JSONSerialization.jsonObject(with: data, options: [])
if let status = (json as AnyObject).value(forKey:"OK") as! Bool? {
DispatchQueue.main.async { //GUI thread
completion(true, status, nil)
}
}
} catch let error {
print(error.localizedDescription)
DispatchQueue.main.async { //GUI thread
completion(false, nil, error)
}
}
}
}.resume()
}
You could convert your image data to base64
let base64String = imageData!.base64EncodedString(options: .lineLength64Characters)
and add it as value for a key to your jsonDictionary
jsonDictionary.setValue(base64String, forKey:"image")

how to make HTTPRequest with json in swift

I am making an ios application. I am new to swift and not able to understand my code. can anyone please help me to understand what is going on with my code.
This is login application on adding email id if the email exist it should go to next view controller and if not then it should give error. I am getting difficulty in understanding my code .
Here is my code:
class checkLoginViewController: UIViewController {
#IBOutlet weak var checkUsernametextfield: UITextField!
#IBAction func checkUsernameButton(_ sender: UIButton) {
print("Clicked On SUbmit !!!!")
//Read Value from Text
let email = checkUsernametextfield.text
let myUrl = URL(string: "http://192.168.0.117/rest/signup.php");
var request = URLRequest(url:myUrl!)
request.httpMethod = "POST"// Compose a query string
let postString = "email=\(String(describing: email))";
request.httpBody = postString.data(using: String.Encoding.utf8);
let task = URLSession.shared.dataTask(with: request) { (data: Data?, response: URLResponse?, error: Error?) in
if error != nil
{
print("error=\(String(describing: error))")
return
}
// You can print out response object
print("response = \(String(describing: response))")
//Let's convert response sent from a server side script to a NSDictionary object:
do {
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary
if let parseJSON = json {
// Now we can access value of First Name by its key
let emailValue = parseJSON["email"] as? String
print("email: \(String(describing: emailValue))")
}
} catch {
print(error)
}
}
task.resume()
Output:
Clicked On SUbmit !!!! response = Optional( { URL: http://192.168.0.117/rest/signup.php } { Status
Code: 200, Headers {
Connection = (
"Keep-Alive"
);
"Content-Length" = (
61
);
"Content-Type" = (
"application/json"
);
Date = (
"Mon, 12 Mar 2018 06:35:58 GMT"
);
"Keep-Alive" = (
"timeout=5, max=100"
);
Server = (
"Apache/2.4.27 (Ubuntu)"
); } }) email: nil
Maybe try this. Hope it works.
let url = URL(string:"http://192.168.0.117/rest/signup.php")
let parameters = ["email": checkUsernametextfield.text]
var request = URLRequest(url : url!)
request.httpMethod = "POST"
request.httpBody = try? JSONSerialization.data(withJSONObject:parameters, options: [])
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
let session = URLSession.shared
session.dataTask(with: request, completionHandler: { (data, response, error) in
if let data = data {
do {
let json = try? JSONSerialization.jsonObject(with: data, options: []) as! Dictionary<String, Any>
if let json = json {
print("HERE SHOULD BE YOUR JSON \(json)")
}
}
} else {
print("Error \(String(describing: error?.localizedDescription))")
}
}).resume()
Here is way to send request.
enter code here
static func downloadConfig(url:URL, completion:#escaping (_ sucess:Bool , _ jsonObject: [String: String]?)->() ) {
var request = URLRequest(url: url)
request.setValue("application/x-www-form-urlencoded",
forHTTPHeaderField: "Content-Type")
request.httpMethod = "POST"
let postString = "id=13&name=Jack"
request.httpBody = postString.data(using: .utf8)
URLSession.shared.dataTask(with: request) { (data,response,error) in
if let data = data ,let httpURLResponse = response as? HTTPURLResponse, httpURLResponse.statusCode == 200 {
do {
if let todoJSON = try JSONSerialization.jsonObject(with: data, options: []) as? [String: String]{
completion(true,todoJSON)
}
else
{
completion(false,nil)
}
}
catch {
//erro parsing
completion(false,nil)
}
}
else
{
completion(false,nil)
}
}.resume()
}
use this download json function in this way.
//Download Json File
let base_url = "base_url"
let urlstr = String.init(format: "%#", base_url)
let url = URL(string: urlstr)
GameUtil.downloadConfig(url: url!) {
(sucess: Bool , jsonObject: [String:String]?) in
if sucess , jsonObject != nil
{
self.configJson = jsonObject!
}
}

Response of JSONSerialization.jsonObject is nil with the method POST in swift 3

this is an example for something i want to do but the line if let json = try JSONSerialization.jsonObject(with: data) as? [String: String] is false because the return of JSONSerialization.jsonObject is nil
func parser(lbl: UILabel){
let postString = "xxx=xxx&xxxx=xxxx==&xxxxx=xxxxx&xxxxxx=xxxxxx&xx=xx"
let url = URL(string: "http://xxxxxxxxxx.com/xxxxxx/xxxxx/xxxxxx.php")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = postString.data(using: .utf8)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data else {
lbl.text = "error";
return
}
do {
if let json = try JSONSerialization.jsonObject(with: data) as? [String: String] {
DispatchQueue.main.async {
let error = Int(json["success"]!)
let message = json["message"]
lbl.text = message
}
}
} catch let parseError {
print("error to parse: \(parseError)")
let responseString = String(data: data, encoding: .utf8)
print("response`enter code here` : \(responseString!)")
}
}
task.resume()
}
Try this:
var resultFromServer: Any?
resultFromServer = try JSONSerialization.jsonObject(with: data!, options: [])
This should give you resultFromServer as type of Any?, simply check and typecast depending on the basis of the response you are getting, an array or a dictionary.
Like
if let respdict = resultFromServer as? [String : Any] {
//respone in dictionary format
}
else if let respArr = resultFromServer as? [Any]{
//response is array type
}
else if let stringRespt = String(data: data, encoding: .utf8){
//resp is string
}
Just make changes as per your JSON