cannot parse json using swift in iOS - ios

I'm trying to get value from json but it is giving this error
type of expression is ambiguous without more context
My ViewController code is
Alamofire.request(.GET, "http://resturl.com/rest/loginuser",
parameters: ["password":uPwd,"username": uEmail,], encoding: .JSON).responseJSON() {
(request,response, data,error) in
let jsonData = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: &error) as? NSDictionary // it is giving error here
if let parseJson=jsonData{
var result:String=parseJson[""] as String!;
}
}
I've searched internet but couldn't find any appropriate solution. Please guide me with this

Alamofire.request(.GET, "http://resturl.com/rest/loginuser",
parameters: ["password":uPwd,"username": uEmail,], encoding: .JSON)
.responseJSON { _, _, JSON, _ in
if let parseJson=JSON{
println(parseJson)
}
}

First thing the data will return in json format. So don't need to convert it in json format. So please use my code. Hope it will help you.
Second thing remove last semicolon(, ) which is extra in this line.
["password":uPwd,"username": uEmail,]
Alamofire.request(.GET, "http://resturl.com/rest/loginuser",
parameters: ["password": uPwd,"username": uEmail], encoding: .JSON).responseJSON() {
(request,response, data,error) in
if let jsonData : NSDictionary = data as! [NSDictionary : AnyObject]{
// do stuff over here
}
else{
println(data)
println(error)
}
}

Related

Alamofire doesnt allow to send object directly

My API only accepts object as the body , but alamofire only sends Dictionary as an object, which my server is not accepting requesting help
I have to call an API which is a post api using alamofire
as soon as i convert the model to dictionary and dicitionary to json
and post it Alamofire does not allow me to post a string
it allows me to send a dictionary which my api does not accept
["key":"value"]- Not acceptable
{"key":"value"}- Acceptable
Can anyone share any solution?
I am using Swift 5 , Xcode 10, Alamofire 4.8.2
do{
let d = try data.asDictionary()
jsonString = DictionaryToJSON(data: dictionary)
} catch {
print(error)
}
Alamofire.request(url, method: .post, parameters: jsonString, encoding: .utf8, headers: [: ]).responseJSON { (res) in
print(res.result)
print("Request Data \(res.request) \n Dictionary \(jsonString)")
do {
let d = try JSONDecoder().decode([OTPMessage].self, from: res.data!)
print(d[0].message)
} catch {
print(error)
}
}
// Dictionary to JSON
func DictionaryToJSON(data: [String:Any])->String {
if let theJSONData = try? JSONSerialization.data(
withJSONObject: data,
options: .prettyPrinted
),
let theJSONText = String(data: theJSONData, encoding: String.Encoding.ascii) {
print("JSON string = \n\(theJSONText)")
return theJSONText
}
else {
return ""
}
}
// Object to Dictionary
extension Encodable {
func asDictionary() throws -> [String: Any] {
let data = try JSONEncoder().encode(self)
guard let dictionary = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String: Any] else {
throw NSError()
}
return dictionary
}
}
//Struct
struct OTPMessage:Codable {
var message = String()
}
You don't have to convert your dictionary to a JSON String because Alamofire can do the encoding, see this example.
I suggest you to change your code to something like this
do{
let dictionary = try data.asDictionary()
Alamofire.request(url, method: .post, parameters: dictionary, encoding: .JSON, headers: [:]).responseJSON { (res) in
print(res.result)
print("Request Data \(res.request) \n Dictionary \(jsonString)")
do{
let d = try JSONDecoder().decode([OTPMessage].self, from: res.data!)
print(d[0].message)
}catch{
print(error)
}
}
} catch{
print(error)
}
With Alamofire you can not do this. What you need to do is creating a URLRequest object and setting the httpBody property of it and then passing it to Alamofire.
URLRequest allows you to have Data as POST body.
var request = URLRequest(url: urlFinal)
request.httpMethod = HTTPMethod.post.rawValue
request.allHTTPHeaderFields = dictHeader
request.timeoutInterval = 10
request.httpBody = newPassword.data(using: String.Encoding.utf8)
Alamofire.request(request).responseString { (response) in
if response.response!.statusCode >= 200 && response.response!.statusCode <= 300 {
completion("success")
}else {
completion("failed")
}
}
here newPassword is string. from there I created the Data object. You have to convert your Custom class object to Data object.

Assigning a long JSON response to Dictionary produces a Thread error

When trying to assign a long JSON response to a Dictionary, I get either
nil
or
Thread 1:EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
Assigning a short response works fine. Here is my code
func getUserInfo() {
let access_token : String = accessToken_json_response["access_token"] ?? "empty"
if access_token != "empty" {
Alamofire.request("https://api.github.com/user?access_token=\(access_token)").responseJSON { response in
if let json = response.result.value {
print(json) //The JSON prints, but takes more than a second to do so.
self.getUser_json_response = json as? Dictionary<String, String> //This produces the thread error when the response is long.
print(self.getUser_json_response) //This either prints nil, or a thread error produces in the previous instruction
}
}
}
}
First of all you are casting to an optional dictionary so it should be conditional binding i.e:
if let unwrappedJson = json as? ....
Second, you should cast to [String : Any] i.e:
if let unwrappedJson = json as? [String : Any]
You have to serialise the response into json and then you can use it as dictionary.
eg: let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]
then print this json
Or
Use this link, this is latest update from apple to code and encode json response according to your class or model.
Automatic JSON serialization and deserialization of objects in Swift
may this help..
Alamofire.request(UrlStr, method: .post, parameters: params, encoding: URLEncoding.default, headers: nil)
.validate()
.responseJSON { response in
switch response.result {
case .success:
if let JSON = response.result.value {
print("JSON: \(JSON)")
let jsonResponse = (JSON as? [String:Any]) ?? [String:Any]()
print("jsonResponse: \(jsonResponse)")
}
case .failure(let error):
print(error.localizedDescription)
}
}

ObjectMapper and Alamofire issue for Swift 3 Alamofire version for Alamofire 4

I have recently migrated to Swift so please be patient and supportive.
I used the code from Object Mapper github page correcting the Syntax for Alamofire 4
let URL = "https://raw.githubusercontent.com/tristanhimmelman/AlamofireObjectMapper/d8bb95982be8a11a2308e779bb9a9707ebe42ede/sample_json"
Alamofire.request(URL).response { (response: DataResponse<WeatherResponse>) in
let weatherResponse = response.result.value
print(weatherResponse?.location)
if let threeDayForecast = weatherResponse?.threeDayForecast {
for forecast in threeDayForecast {
print(forecast.day)
print(forecast.temperature)
}
}
}
But I get the following error as shown in screenshot.
This way you should call method in Alamofire :
func getWeatherDataResponseFromServer() {
let URL = "https://raw.githubusercontent.com/tristanhimmelman/AlamofireObjectMapper/d8bb95982be8a11a2308e779bb9a9707ebe42ede/sample_json"
//AlamoFire request
Alamofire.request(URL, method: .get, parameters: nil, encoding: JSONEncoding.default, headers: nil).responseJSON { response in
do {
let reponse = try JSONSerialization.jsonObject(with: response.data!, options: JSONSerialization.ReadingOptions()) as! Dictionary<String, AnyObject>
} catch {
print(error)
}
}
}
Hope this gonna help you.

Alamofire 4 and special characters in JSON

I've got a problem with special characters with Alamofire 4.The JSON contains æ, ø and å and the browser shows them fine, also my previous solution using SwiftyJSON did.Alamofire 4 shows something like this instead:
U00e6
Using this call:
Alamofire.request(specificURL, method: .get, parameters: param, encoding: URLEncoding.default, headers: nil).responseJSON { (response: DataResponse<Any>) in
print(response)
}
What to do to solve this?
Edit:
Alamofire.request(url, method: .get, parameters: param, encoding: JSONEncoding.default)
.responseJSON { response in
switch response.result {
case .success(let value) :
print(response.request) // original URL request
print(response.response) // HTTP URL response
print(response.data) // server data
print(response.result) // result of response serialization
if let JSON = response.result.value as! [String:AnyObject]!{
print("JSON: ",JSON)
self.arrUser = Mapper<Users>().mapArray(JSONArray:JSON["user"] as! [[String : Any]])!
self.tableView.reloadData()
}
case .failure(let encodingError):
//Print error
}
}
I got the issue that I have added æ in json response and try to print.
Output:
JSON: Optional(<__NSArrayI 0x600000050320>(
{
"email_address" = "testwts06#gmail.com";
username = "testwts06 \U00e6";
},
{
"email_address" = "testwts01#gmail.com";
username = "testwts01 \U00eb";
},
{
"email_address" = "testwts100#gmail.com";
username = testwts100;
})
While displaying it display in correct format.
Swift 3 update for Ekta's answer:
let encodedURL = specificURL.addingPercentEncoding(withAllowedCharacters: NSCharacterSet.urlQueryAllowed)
Seems the typical serialization error due to wrong JSON encoding, probably your response status code is 3840.
JSON text SHALL be encoded in UTF-8, UTF-16, or UTF-32.
You could try to convert the response data to correct UTF8 encoding:
let datastring = NSString(data: response.data!, encoding: String.Encoding.isoLatin1.rawValue)
let data = datastring!.data(using: String.Encoding.utf8.rawValue)
do {
let object = try JSONSerialization.jsonObject(with: data!, options: .allowFragments)
let jsonDic = object as! NSDictionary
print(" ok, successfully converted..\(jsonDic)")
} catch let aError as Error {
// print and handle aError
}
Hope it helps you.
Here is a simple String extension that solves the issue:
extension String {
func fixUnicode() -> String {
var copy = self as NSString
let regex = try! NSRegularExpression(pattern: "\\\\U([A-Z0-9]{4})", options: .caseInsensitive)
let matches = regex.matches(in: self, options: [], range: NSMakeRange(0, characters.count)).reversed()
matches.forEach {
let char = copy.substring(with: $0.rangeAt(1))
copy = copy.replacingCharacters(in: $0.range, with: String(UnicodeScalar(Int(char, radix: 16)!)!)) as NSString
}
return copy as String
}
}

JSON String to NSDictionary with Swift

I am trying to create a dictionary from data that is held in a server, I receive the data but I cannot convert the data to an NSDictionary, I believe it is held in an NSData Object
let JSONDictionary: Dictionary = NSJSONSerialization.JSONObjectWithData(JSONData!, options: nil, error: &error) as NSDictionary
This line of code is the one giving me the problem, it throws a BAD_EXEC_INSTRUCTION.
MY Question: How can I turn a JSON into an NSDictionary?
Your code does not do any error handling. But it can (and if this data comes from a web service, will) fail in multiple ways.
You have to make sure that your data object actually exists
You have to make sure that the data object can be converted to JSON
You have to make sure that the JSON actually contains a Dictionary
You should use Swifts conditional cast and it's optional binding capabilities.
The optional binding if let JSONData = JSONData checks that JSONData is not nil. The force unwrap (JSONData!) you use might crash if no data could be received.
The optional binding if let json = NSJSONSerialization.JSONObjectWithData checks if the data could be converted to a JSON object. The conditional cast as? NSDictionary checks if the JSON object is actually a dictionary. You currently don't use these checks, you cast the objects as NSDictionary. Which will crash, if the object is not valid json, or if its not a dictionary.
I would recommend something like this:
var error: NSError?
if let JSONData = JSONData { // Check 1
if let json: AnyObject = NSJSONSerialization.JSONObjectWithData(JSONData, options: nil, error: &error) { // Check 2
if let jsonDictionary = json as? NSDictionary { // Check 3
println("Dictionary received")
}
else {
if let jsonString = NSString(data: JSONData, encoding: NSUTF8StringEncoding) {
println("JSON String: \n\n \(jsonString)")
}
fatalError("JSON does not contain a dictionary \(json)")
}
}
else {
fatalError("Can't parse JSON \(error)")
}
}
else {
fatalError("JSONData is nil")
}
You could merge check 2 and 3 into one line and check if NSJSONSerialization can create a NSDictionary directly:
var error: NSError?
if let JSONData = JSONData { // Check 1.
if let JSONDictionary = NSJSONSerialization.JSONObjectWithData(JSONData, options: nil, error: &error) as? NSDictionary { // Check 2. and 3.
println("Dictionary received")
}
else {
if let jsonString = NSString(data: JSONData, encoding: NSUTF8StringEncoding) {
println("JSON: \n\n \(jsonString)")
}
fatalError("Can't parse JSON \(error)")
}
}
else {
fatalError("JSONData is nil")
}
Make sure to replace fatalError with appropriate error handling in your production code
Update for Swift 2.
Now you must use it inside a try catch block.
do {
let responseObject = try NSJSONSerialization.JSONObjectWithData(data, options: []) as! [String:AnyObject]
} catch let error as NSError {
print("error: \(error.localizedDescription)")
}
Here jsonResult will give you the response in NSDictionary:
let url = NSURL(string: path)
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithURL(url!, completionHandler: {data, response, error -> Void in
println("Task completed")
if(error != nil) {
// If there is an error in the web request, print it to the console
println(error.localizedDescription)
}
var err: NSError?
var jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &err) as NSDictionary
if(err != nil) {
// If there is an error parsing JSON, print it to the console
println("JSON Error \(err!.localizedDescription)")
}
})
task.resume()

Resources