Failure response from alamofire swift3 - ios

Hello I get stucked with alamofire.
let keys = [CNContactPhoneNumbersKey, CNContactGivenNameKey]
let request = CNContactFetchRequest(keysToFetch: keys as [CNKeyDescriptor])
let contactStore = CNContactStore()
do {
try contactStore.enumerateContacts(with: request) {
(contact, stop) in
// Array containing all unified contacts from everywhere
self.contacts.append(contact)
}
}
catch {
print("unable to fetch contacts")
}
var contactArray = [[String:String]]()
for i in 0..<contacts.count{
var mobiles = ""
for num in contacts[i].phoneNumbers {
mobiles = num.value.stringValue
}
var theDict = ["contact_id": "\(i)", "full_name": contacts[i].givenName, "mobile_number": "\(mobiles)"]
contactArray.append(theDict)
}
dictParams["contacts"] = dictContacts
let theParams = ["contacts":contactArray] as [String:AnyObject]
print("dict theParams: \(theParams)")
this is the printed parameters
dict theParams: ["contacts": <Swift._SwiftDeferredNSArray 0x604000233280>(
{
"contact_id" = 0;
"full_name" = Kate;
"mobile_number" = "62123123";
},
{
"contact_id" = 1;
"full_name" = Daniel;
"mobile_number" = "621231123";
},
{
"contact_id" = 2;
"full_name" = John;
"mobile_number" = "625435345";
}
)
]
and i send it to alamofire with this code
func sendFriendList(dictContacts: [String:AnyObject] ,successBlock:((_ isSuccess: Bool, _ theFriendsResponse: FriendsResponse)->Void)?,errorBlock:((_ errorString:String)->Void)? )-> Void
{
Alamofire.request("url/ListRetrieve",
method: .post,
parameters: dictContacts,
encoding: URLEncoding.default,
headers: headers)
.responseJSON { response in
print("this is response retrieve \(response)")
and the response from alamofire:
this is the response = retrieve FAILURE: responseSerializationFailed(Alamofire.AFError.ResponseSerializationFailureReason.jsonSerializationFailed(Error Domain=NSCocoaErrorDomain Code=3840 "Invalid value around character 1." UserInfo={NSDebugDescription=Invalid value around character 1.}))
but if I change the parameters only string like this
["contacts":"test contact"]
the alamofire response become success and it's work.
please help me :) thank you

It's not the Alamofire issue. The api needs the "contacts" parameter as String and you are sending an Array of Dictionaries. If you are sending the Array data in "contacts" parameter ask the api developers to change the parameter type or if possible send string as data in "contacts" parameter.
The issue :
this is the response = retrieve FAILURE: responseSerializationFailed(Alamofire.AFError.ResponseSerializationFailureReason.jsonSerializationFailed(Error Domain=NSCocoaErrorDomain Code=3840 "Invalid value around character 1." UserInfo={NSDebugDescription=Invalid value around character 1.}))
is also stating the invalid character only.

My Parameters is like
// .toJson to your array object or dictonary object and try out
let parameters: [String : Any] = [
"products":[
["pid":"72","qnty":"1"],
["pid":"4","qnty":"1"],
["pid":"3","qnty":"1"]
].toJson ?? "[]",
]
Use this extension for converting Array object to JSON string.
extension Array where Element: Codable {
public var toData: Data {
let encoder = JSONEncoder()
do {
return try encoder.encode(self)
}
catch {
fatalError(error.localizedDescription)
}
}
public var toJson: String? {
return toData.toJson
}
}

Use responseString instead of responseJSON. Then use JSONSerialization to convert response to JSON.
Something like :
JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]
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
}

Related

How to convert stored values to JSON format using Swift?

I am trying to convert stored coredata values to JSON format and the JSON format value need to assign a single variable, because this generated JSON I need to send to server. Below code I tried to get coredata stored values but don’t know how to generate JSON required format.
Getting values from coredata
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "User")
do {
let results = try context.fetch(fetchRequest)
let dateCreated = results as! [Userscore]
for _datecreated in dateCreated {
print("\(_datecreated.id!)-\(_datecreated.name!)") // Output: 79-b \n 80-c \n 78-a
}
} catch let err as NSError {
print(err.debugDescription)
}
Need to Convert Coredata Value to Below JSON format
{
    "status": true,
    "data": [
        {
            "id": "20",
            "name": "a"
        },
        {
            "id": "21",
            "name": "b"
        },
        {
            "id": "22",
            "name": "c"
        }
    ]
}
Probably the easiest is to convert your object(s) to either dictionaries or arrays (depending on what you need).
First you need to be able to convert your Userscore to dictionary. I will use extension on it since I have no idea what your entity looks like:
extension Userscore {
func toDictionary() -> [String: Any]? {
guard let id = id else { return nil }
guard let name = name else { return nil }
return [
"id": id,
"name": name
]
}
}
Now this method can be used to generate an array of your dictionaries simply using let arrayOfUserscores: [[String: Any]] = userscores.compactMap { $0.toDictionary() }.
Or to build up your whole JSON as posted in question:
func generateUserscoreJSON(userscores: [Userscore]) -> Data? {
var payload: [String: Any] = [String: Any]()
payload["status"] = true
payload["data"] = userscores.compactMap { $0.toDictionary() }
return try? JSONSerialization.data(withJSONObject: payload, options: .prettyPrinted)
}
This will now create raw data ready to be sent to server for instance
var request = URLRequest(url: myURL)
request.httpBody = generateUserscoreJSON(userscores: userscores)
You can use the properties of an Encodable to make this happen. This has the added benefit of not resorting to the Any type.
For the JSON, you could use the following types:
struct JSONMessage: Encodable {
var status: Bool
var data: [JSONDataEntry]
}
struct JSONDataEntry: Encodable {
var id: String
var name: String
}
Then you can adjust your do/try/catch as follows:
do {
let results = try context.fetch(fetchRequest)
let dateCreated = results as! [Userscore]
// *starting here*
let data = dateCreated.map { JSONDataEntry(id: String($0.id!), name: $0.name!) }
let status = true // <- not sure where status comes from, so adding here
let message = JSONMessage(status: status, data: data)
let jsonData = try JSONEncoder().encode(message)
if let json = String(data: jsonData, encoding: .utf8) {
// do something with the JSON string
print(json)
}
// *ending here*
} catch let err as NSError {
print(err.debugDescription)
}

How to send json data with json object in swift 4

I need to send json to server in following order
data:{"firstname":"Alpha","lastname":"Beta"}
In this the data key is outside of json like [data:json] but when I am serialization it making the request as
{
"data" : {
"firstname" : "alpha",
"lastname" : "beta"
}
}
These are my models :
struct UserDetail :Codable {
let data :CreateProfileModel
}
struct CreateProfileModel :Codable {
let firstname :String
let lastname :String
}
Data I am adding in these models
let profileInfo = CreateProfileModel(firstname: "alpha" , lastname: "beta")
let userDetails = UserDetail(data: profileInfo)
This is the json encoding that I am doing using swift :
let jsonEncoder = JSONEncoder()
jsonEncoder.outputFormatting = .prettyPrinted
do{
let userData = try jsonEncoder.encode(userDetails)
print(String(data: userData, encoding: .utf8)!)
networkListener.requestPost(endpoint: endpoint, data: userData , headerValue: nil)
}catch{
print(error)
}
In requestPost method
func requestPost(endpoint : String , data :Data,headerValue : String?){....
request.httpbody = data
}
I am adding that data the request.httpbody.
How can i add data key with profileInfo ?
Try this Code:
var columnValus:[String:Any] = [:]
columnValus["firstname"] = userDetails.data.firstname
columnValus["lastname"] = userDetails.data.lastname
let userData = [
"data": columnValus
] as [String : Any]
do {
let postData = try JSONSerialization.data(withJSONObject: userData, options: [])
networkListener.requestPost(endpoint: endpoint, data: postData , headerValue: nil)
}catch let error as NSError {
print(error)
}
If the API requires (effectively) HTML form data, you'll need to construct the body yourself and extract bits of JSON.
Try:
let userData = try jsonEncoder.encode(userDetails.data)
let postBodyString = "data:\(userData)"
let postBodyData = postBodyString.data(using: String.Encoding.utf8)
networkListener.requestPost(endpoint: endpoint, data: postBodyData, headerValue: nil)

Swift 4 parse string to json object

I have implement qr code scanner, Where in "metadataOutput" delegate method I have received response which has key like "stringValue", Value of this key is
stringValue "'{ "part_number":"154100102232",
"lot_number":"03S32401701344"}'"
I want parse string value to json object, but I am not able to do that.
let data = stringValue.data(using: .utf8)!
do {
if let json = try JSONSerialization.jsonObject(with: data, options : .allowFragments) as? [AnyHashable:Any]
{
print("Json:::",json)
// post a notification
// NotificationCenter.default.post(name: NSNotification.Name(rawValue: "SCANNER_DATA"), object: nil, userInfo: json)
} else {
print("bad json")
}
} catch let error as NSError {
print(error)
}
I have followed above approach to parse string to json, but I have found following error.
Error Domain=NSCocoaErrorDomain Code=3840 "Invalid value around
character 0." UserInfo={NSDebugDescription=Invalid value around
character 0.}
Can anyone have any idea about this?
Better have an extension to String like this
extension String{
func toDictionary() -> NSDictionary {
let blankDict : NSDictionary = [:]
if let data = self.data(using: .utf8) {
do {
return try JSONSerialization.jsonObject(with: data, options: []) as! NSDictionary
} catch {
print(error.localizedDescription)
}
}
return blankDict
}
}
Use like this
let dict = stringValue.toDcitionary()
Or you can use pod for all these kind of work from UtilityKit on github https://github.com/utills/UtilityKit
This works with me , You string has ' character around trailing "' content '"
let stringValue = """
{"part_number":"154100102232","lot_number":"03S32401701344"}
"""
let data = stringValue.data(using: .utf8)!
do {
if let json = try JSONSerialization.jsonObject(with: data) as? [String:Any]
{
print("ewtyewytyetwytewytewtewytew",json)
} else {
print("ewtyewytyetwytewytewtewytew","bad json")
}
} catch let error as NSError {
print("ewtyewytyetwytewytewtewytew",error)
}

pull data from parsed Json with swift

I want to get my CampaignList from JsonObject which I parsed before. But it gives fatal error while it is running.
Error
"fatal error: unexpectedly found nil while unwrapping an Optional value"
self.CampaignArray = Campaigns as! NSMutableArray
The code :
var CampaignArray:NSMutableArray = []
func Get(){
let res: String = ""
let jsonObject = ["PhoneNumber": "xxxxx"]
let Jsn = JsonClass(value: jsonObject, text: res)
Alamofire.request(.POST, "http://MYURL",parameters: jsonObject,
encoding: .JSON).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 = resultValue
print(responseJSON)
let result = Jsn.convertStringToDictionary(responseJSON as! String)!
print("result: \(result)")
let Campaigns = (result as NSDictionary)["Campaigns"]
print(Campaigns)
self.CampaignArray = Campaigns as! NSMutableArray
let notifications = (result as NSDictionary)["Notifications"]
print(notifications)
break
case .Failure(let error):
NSLog("Error result: \(error)")
// Here I call a completionHandler I wrote for the failure case
return
}
}
}
And my response Json is:
json: {"CampaignList":[
{"Bonus":"5","CampaignId":"zQUuB2RImUZlcFwt3MjLIA==","City":"34"}
{"Bonus":"3","CampaignId":"VgYWLR6eL2mMemFCPkyocA==","City":"34"}],
"MemberId":"ZBqVhLv\/c2BtMInW52qNLg==",
"NotificationList":[{"Notification":"Filiz Makarnadan Milli Piyango Çekiliş Hakkı Kazanmak İster misin ?","PhoneNumber":"555555555"}]}
JSON you provide is invalid. There is lack of , in Campaigns dictionary.
Valid JSON looks like:
{
"CampaignList": [
{
"Bonus": "5",
"CampaignId": "zQUuB2RImUZlcFwt3MjLIA==",
"City": "34"
},
{
"Bonus": "3",
"CampaignId": "VgYWLR6eL2mMemFCPkyocA==",
"City": "34"
}
],
"MemberId": "ZBqVhLv/c2BtMInW52qNLg==",
"NotificationList": [
{
"Notification": "Filiz Makarnadan Milli Piyango Çekiliş Hakkı Kazanmak İster misin ?",
"PhoneNumber": "555555555"
}
]
}
fatal error: unexpectedly found nil while unwrapping an Optional value
You receive this error because you try cast nil to NSDictionary object.
You have no Campaigns key in JSON you provide, so when you try to get this key from JSON you get nil. In next step you try cast this nil to NSDictionary.
Try use CampaignList key to get data you want.
let result: [String: AnyObject] = Jsn.convertStringToDictionary(responseJSON as! String)!
let campaigns: [Campaign] = result["CampaignList"] as! [Campaign]
print(Campaigns)
self.CampaignArray = campaigns
let notifications = result["NotificationList"]
print(notifications)
The same case will be with your Notifications key from JSON Dictionary.
You should also use swift types over objective-c NSDictionary and NSArray.
Try to use SwiftyJSON (https://github.com/SwiftyJSON/SwiftyJSON)
This library (pod) is very simple and has detailed documentation.
Your example:
I put son file "data.json" in my project and read it. Thank Daniel Sumara for your json example correction.
if let path = NSBundle.mainBundle().pathForResource("data", ofType: "json") {
if let data = NSData(contentsOfFile: path) {
let json = JSON(data: data)
if let CampaignList = json["CampaignList"].array {
for index in 0 ..< CampaignList.count {
print("Campaign [\(index)]")
if let CampaignId = CampaignList[index]["CampaignId"].string {
print(" CampaignId: \(CampaignId)")
}
if let City = CampaignList[index]["City"].string {
print(" City: \(City)")
}
if let Bonus = CampaignList[index]["Bonus"].string {
print(" Bonus: \(Bonus)")
}
}
}
if let MemberId = json["MemberId"].string {
print("MemberId: \(MemberId)")
}
if let NotificationList = json["NotificationList"].array {
print("NotificationList")
for notification in NotificationList {
if let Notification = notification["Notification"].string {
print(" Notification: \(Notification)")
}
if let PhoneNumber = notification["PhoneNumber"].string {
print(" PhoneNumber: \(PhoneNumber)")
}
}
}
}
}
Also you can use Alamofire-SwiftyJSON (https://github.com/SwiftyJSON/Alamofire-SwiftyJSON)
P.S. you have fatal errors because you do not check if value is nil. read about "if let" expression (https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/OptionalChaining.html)

valueForKeyPath with nested JSON

I have a problem in using valueForKeyPath, here the way I get the dataVersion value and it's works perfectly:
Alamofire.request(.GET, "https://www.amazon.fr/s", parameters:parameters)
.responseJSON { (_, _, JSON, _) -> Void in
let priceResult: String? = JSON?.valueForKeyPath("reponseMetadata.dataVersion") as String?
println(priceResult)
}
But when I try to access the url value like this, it's fail
Alamofire.request(.GET, "https://www.amazon.fr/s", parameters:parameters)
.responseJSON { (_, _, JSON, _) -> Void in
let priceResult: String? = JSON?.valueForKeyPath("preloadImages.images.url") as String?
println(priceResult)
}
Here my Json :
{
responseMetadata: {
dataVersion: "v0.1"
},
preloadImages: {
images: [
{
url: "http://ecx.images-amazon.com/images/I/51K4P7REBKL._SL500_AC_.jpg"
}
]
}
}
I new in IOs so any help would be most welcome !
preloadImages.images is an array of objects (Array of Dictionary in swift-speak) so your valueForKeyPath won't work. Unfortunately, there isn't any way to index an array through valueForKeyPath, so you'll have to get it less directly:
let string = "{ \"responseMetadata\": { \"dataVersion\": \"v0.1\" }, \"preloadImages\": { \"images\": [ { \"url\": \"http://ecx.images-amazon.com/images/I/51K4P7REBKL._SL500_AC_.jpg\" } ] } }"
var error : NSError?
let data = string.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)
if let json: AnyObject = NSJSONSerialization.JSONObjectWithData(data!, options: .allZeros, error: &error) {
if let images = json.valueForKeyPath("preloadImages.images") as? Array<Dictionary<String,String>> {
let url = images[0]["url"]
println("url = \(url)")
}
} else {
println("json failed: \(error)")
}
Note that your JSON also isn't valid as shown since the object keys aren't quoted, I assume you're dumping the JSON variable using println instead of showing the actual JSON data.

Resources