I'm using AFNetworking to retrieve weather info form openweathermap API.
let manager = AFHTTPSessionManager()
manager.requestSerializer = AFJSONRequestSerializer()
let url = "http://api.openweathermap.org/data/2.5/weather"
let params = ["lat": latitude,"lon": longitude,"cnt": 0]
manager.get(url, parameters: params,
success: {(operation: URLSessionDataTask,responseObject: AnyObject!) in print("JSON" + responseObject.description!) },
failure: {(operation: URLSessionDataTask?,error: Error) in print(error.localizedDescription)}
)
highlighting at responseObject.description indicated that 'Anyobject' is not a subtype of 'NSProxy'
If remove .description the error will disappear.
platform:xcode 8.3.2 swift:3
'Anyobject' is not a subtype of 'NSProxy'
First on of all the get method you are using is a deprecated one (I assume you have newest AFNetworking version). Please use the new one this way:
let manager = AFHTTPSessionManager()
manager.requestSerializer = AFJSONRequestSerializer()
let url = "http://api.openweathermap.org/data/2.5/weather"
let params = ["lat": 5.0,"lon": 5.0,"cnt": 0]
manager.get(url, parameters: params, progress: nil, success: { (operation, responseObject) in
if let responseObject = responseObject {
print(responseObject)
} else {
print("There is no response object") //assume parsing error for JSON
}
}) { (operation, error) in
print(error.localizedDescription)
}
As the last tip: if you are using Swift, better use Alamofire:
https://github.com/Alamofire/Alamofire
It supports lots of nice features coming from Swift and much nicer error handling. For example Alamofire treats parsing error as real errors and calls failure block, not success block like ANetworking.
Also allows you to easily integrate some JSON parsing libs like SwiftJSON
https://github.com/SwiftyJSON/SwiftyJSON
In my project I need to send JSON object in web service API call. I have converted JSON from array.
do {
let theJSONData = try NSJSONSerialization.dataWithJSONObject(
param ,
options: NSJSONWritingOptions(rawValue: 0))
var theJSONText : String = String(data: theJSONData,
encoding: NSASCIIStringEncoding)!
print(theJSONText)
theJSONText = theJSONText.stringByReplacingOccurrencesOfString("\\", withString: "", options: NSStringCompareOptions.LiteralSearch, range: nil)
print(theJSONText)
let newParam = ["ESignData":theJSONText]
} catch let error as NSError {
print(error)
}
it print string correctly as
{"EntNum":"47","JobNo":"1737753","ClientID":"100","HospNo":"1","QAReason":"","DoctorNo":"1694","Action":"Sign"}
{"EntNum":"47","JobNo":"1737753","ClientID":"100","HospNo":"1","QAReason":"","DoctorNo":"1694","Action":"Sign"}
Now When I try to send this newParam dictionary in API call, it contains "\" in string parameters of JSON string.
WebService.PostURL(mainLink, methodname: ESIGNTHISDOC, param: newParam, userName: AUTH_USERNAME, password: AUTH_PWD, CompletionHandler: { (success, response) in
})
And in that web service method I have print param.
Param = {
ESignData = "{\"EntNum\":\"47\",\"JobNo\":\"1737753\",\"ClientID\":\"100\",\"HospNo\":\"1\",\"QAReason\":\"\",\"DoctorNo\":\"1694\",\"Action\":\"Sign\"}";
}
Now in this I know it is obvious in iOS because of " in string. Now the problem is that there are lots of APIs working in android app, and the API developer doesn't want to update his code according to us.
I know this problem happens because of adding JSON string in dictionary as parameter. But I have not proper justification for that so if any proof will be also helpful for me to convince him.
Any solution to convert the JSON string without backslash in iOS? I need to fix from my side if possible. Any help will be appreciate.
EDIT :
On server side it needs like
ESignData = {"EntNum":"47","JobNo":"1737753","ClientID":"100","HospNo":"1","QAReason":"","DoctorNo":"1694","Action":"Sign"}
If I pass this as parameter in POSTMAN than it gives success message. But not with our object with "\" in it.
EDIT 2:
Now printing the newParam dictionary:
print(newParam)
print("-------------------------")
print(newParam["ESignData"])
And logs :
["ESignData": "{\"EntNum\":\"47\",\"JobNo\":\"1737754\",\"ClientID\":\"100\",\"HospNo\":\"1\",\"QAReason\":\"\",\"DoctorNo\":\"1694\",\"Action\":\"Sign\"}"]
-------------------------
Optional("{\"EntNum\":\"47\",\"JobNo\":\"1737754\",\"ClientID\":\"100\",\"HospNo\":\"1\",\"QAReason\":\"\",\"DoctorNo\":\"1694\",\"Action\":\"Sign\"}")
And by debug :
Printing description of newParam:
▿ 1 elements
▿ [0] : 2 elements
- .0 : "ESignData"
- .1 : "{\"EntNum\":\"47\",\"JobNo\":\"1737754\",\"ClientID\":\"100\",\"HospNo\":\"1\",\"QAReason\":\"\",\"DoctorNo\":\"1694\",\"Action\":\"Sign\"}"
So it shows that it is in our dictionary. All the " are joined by \.
I ran into this exact issue today. For me it appears that the default encoding for any NSURLRequest is a string. So, somewhere between my creating the dictionary request and the server parsing it, the backslashes would appear and the server had problems with my payload.
I solved the issue by explicitly stating that my payload was JSON by setting the content type header.
[authRequest setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
Now when I create JSON data from a dictionary, the backslashes don't appear and the server is able to parse everything correctly.
Code snippet below for completeness:
NSMutableURLRequest *authRequest = [[[NSURLRequest alloc] initWithURL:authURL] mutableCopy];
[authRequest setHTTPMethod:#"POST"];
NSURLSession *session = [NSURLSession sharedSession];
[authRequest setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
NSDictionary *bodyDictionary = #{#"User_Name": user, #"Password_Hash": password};
if ([NSJSONSerialization isValidJSONObject:bodyDictionary]) {
NSError *error;
NSData *bodyData = [NSJSONSerialization dataWithJSONObject:bodyDictionary options:0 error:&error];
if (!error) {
[authRequest setHTTPBody:bodyData];
} else {
NSLog(#"Unable to convert to JSON DATA %#", error.localizedDescription);
}
}
Alamofire.request(.GET, "url").authenticate(user: "", password: "").responseJSON() {
(request, response, json, error) in
println(error)
println(json)
}
This is my request with Alamofire, for a certain request it sometime works, but sometimes i get:
Optional(Error Domain=NSCocoaErrorDomain Code=3840 "The operation couldn’t be completed. (Cocoa error 3840.)" (Invalid value around character 0.) UserInfo=0x78e74b80 {NSDebugDescription=Invalid value around character 0.})
I've read that this can be due to invalid JSON, but the response is a static json string that i have validated in JSON validator as valid. It does contain å ä ö characters and some HTML.
Why am i getting this error sometimes?
I also faced same issue. I tried responseString instead of responseJSON and it worked. I guess this is a bug in Alamofire with using it with django.
In my case , my server URL was incorrect. Check your server URL !!
I got same error while uploading image in multipart form in Alamofire as i was using
multipartFormData.appendBodyPart(data: image1Data, name: "file")
i fixed by replacing by
multipartFormData.appendBodyPart(data: image1Data, name: "file", fileName: "myImage.png", mimeType: "image/png")
Hope this help someone.
May this Help YOu
Alamofire.request(.GET, "YOUR_URL")
.validate()
.responseString { response in
print("Success: \(response.result.isSuccess)")
print("Response String: \(response.result.value)")
}
The same issue happened to me and it actually ended up being a server issue since the content type wasn't set.
Adding
.validate(contentType: ["application/json"])
To the request chain solved it for me
Alamofire.request(.GET, "url")
.validate(contentType: ["application/json"])
.authenticate(user: "", password: "")
.responseJSON() { response in
switch response.result {
case .Success:
print("It worked!")
print(response.result.value)
case .Failure(let error):
print(error)
}
}
I got the same error. But i found the solution for it.
NOTE 1: "It is not Alarmofire error", it's bcouse of server error.
NOTE 2: You don't need to change "responseJSON" to "responseString".
public func fetchDataFromServerUsingXWWWFormUrlencoded(parameter:NSDictionary, completionHandler: #escaping (_ result:NSDictionary) -> Void) -> Void {
let headers = ["Content-Type": "application/x-www-form-urlencoded"]
let completeURL = "http://the_complete_url_here"
Alamofire.request(completeURL, method: .post, parameters: (parameter as! Parameters), encoding: URLEncoding.default, headers: headers).responseJSON { response in
if let JSON = response.result.value {
print("JSON: \(JSON)") // your JSONResponse result
completionHandler(JSON as! NSDictionary)
}
else {
print(response.result.error!)
}
}
}
This is how I managed to resolve the Invalid 3840 Err.
The error log
responseSerializationFailed(Alamofire.AFError.ResponseSerializationFailureReason.jsonSerializationFailed(Error Domain=NSCocoaErrorDomain Code=3840 "Invalid value around character 0." UserInfo={NSDebugDescription=Invalid value around character 0.}))
It was with Encoding Type used in the Request, The Encoding Type used should be acceptedin your Server-Side.
In-order to know the Encoding I had to run through all the Encoding Types:
default/
methodDependent/
queryString/
httpBody
let headers: HTTPHeaders = [
"Authorization": "Info XXX",
"Accept": "application/json",
"Content-Type" :"application/json"
]
let parameters:Parameters = [
"items": [
"item1" : value,
"item2": value,
"item3" : value
]
]
Alamofire.request("URL",method: .post, parameters: parameters,encoding:URLEncoding.queryString, headers: headers).responseJSON { response in
debugPrint(response)
}
It also depends upon the response we are recieving use the appropriate
responseString
responseJSON
responseData
If the response is not a JSON & just string in response use responseString
Example: in-case of login/ create token API :
"20dsoqs0287349y4ka85u6f24gmr6pah"
responseString
I solved using this as header:
let header = ["Content-Type": "application/json",
"accept": "application/json"]
In my case, there was an extra / in the URL .
Maybe it is too late but I solved this problem in another way not mentioned here:
When you use .responseJSON(), you must set the response header with content-type = application/json, if not, it'll crash even if your body is a valid JSON. So, maybe your response header are empty or using another content-type.
Make sure your response header is set with content-type = application/json to .responseJSON() in Alamofire work properly.
Hey guys this is what I found to be my issue: I was calling Alamofire via a function to Authenticate Users: I used the function "Login User" With the parameters that would be called from the "body"(email: String, password: String) That would be passed
my errr was exactly:
optional(alamofire.aferror.responseserializationfailed(alamofire.aferror.responseserializationfailurereason.jsonserializationfailed(error domain=nscocoaerrordomain code=3840 "invalid value around character 0." userinfo={nsdebugdescription=invalid value around character 0
character 0 is the key here: meaning the the call for the "email" was not matching the parameters: See the code below
func loginUser(email: String, password: String, completed: #escaping downloadComplete) {
let lowerCasedEmail = email.lowercased()
let header = [
"Content-Type" : "application/json; charset=utf-8"
]
let body: [String: Any] = [
"email": lowerCasedEmail,
"password": password
]
Alamofire.request(LOGIN_USER, method: .post, parameters: body, encoding: JSONEncoding.default, headers: header).responseJSON { (response) in
if response.result.error == nil {
if let data = response.result.value as? Dictionary<String, AnyObject> {
if let email = data["user"] as? String {
self.userEmail = email
print(self.userEmail)
}
if let token = data["token"] as? String {
self.token_Key = token
print(self.token_Key)
}
"email" in function parameters must match the let "email" when parsing then it will work..I no longer got the error...And character 0 was the "email" in the "body" parameter for the Alamofire request:
Hope this helps
I was sending the improper type (String) to the server in my parameters (needed to be an Int).
Error was resolved after adding encoding: JSONEncoding.default with Alamofire.
Alamofire.request(urlString, method: .post, parameters:
parameters,encoding:
JSONEncoding.default, headers: nil).responseJSON {
response in
switch response.result {
case .success:
print(response)
break
case .failure(let error):
print(error)
}
}
The application I was working on this morning had the same error. I believed it to be a server side error since I was unable to upload a user image.
However, upon checking my custom API, I realized that after adding an SSL certificate to my website that I had not updated the api.swift URLs, the data was unable to post:
let HOME_URL = "http://sitename.io"
let BASE_URL = "http://sitename.io/api"
let UPLOAD_URL = "http://sitename.io/api/user/upload"
I changed the URL's to https://. Problem solved.
In my case I have to add this Key: "Accept":"application/json" to my header request.
Something like this:
let Auth_header: [String:String] = ["Accept":"application/json", "Content-Type" : "application/json", "Authorization":"Bearer MyToken"]
I hope that this can help someone.
I face same issue and problem is in params.
let params = [kService: service,
kUserPath: companyModal.directory_path,
kCompanyDomain: UserDefaults.companyDomain,
kImageObject: imageString,
kEntryArray: jsonString,
kUserToken: UserDefaults.authToken] as [String : Any]
companyModal.directory_path is url. it coerced from string to any which create issues at server side. To resolve this issue I have to give default value which make it string value.
let params = [kService: kGetSingleEntry,
kUserPath: companyModal.directory_path ?? "",
kCompanyDomain: UserDefaults.companyDomain,
kUserToken: UserDefaults.authToken,
kEntryId: id,
] as [String: Any]
Probably you have "/" at the end of your path. If it is not GET request, you shouldn't put "/" at the end, otherwise you'll get the error
I Changed mimeType from "mov" to "multipart/form-data".
Alamofire.upload(multipartFormData: { (multipartFormData) in
do {
let data = try Data(contentsOf: videoUrl, options: .mappedIfSafe)
let fileName = String(format: "ios-video_%#.mov ", profileID)
multipartFormData.append(data, withName: "video", fileName: fileName, mimeType: "multipart/form-data")
} catch {
completion("Error")
}
}, usingThreshold: .init(), to: url,
method: .put,
headers: header)
Worked for me.. :)
For my case:
let header = ["Authorization": "Bearer \(Authserices.instance.tokenid)"]
I forgot the space before \ (after Bearer)
In my case error was due to duplicate email. You can recheck your API on postman to see if response there is OK or not.
In my case, I tried using Postman to get API and this error come from backend.
I am using AFNetworking to GET a plain/text:
let manager = AFHTTPRequestOperationManager()
manager.GET(url, parameters: nil, success: { (op: AFHTTPRequestOperation!, res: AnyObject!) -> Void in
},failure: { (op: AFHTTPRequestOperation!, er:NSError!) -> Void in
println(op,er)
})
The accept content types:
manager.responseSerializer.acceptableContentTypes
[text/javascript, application/json, text/json]
So I got error in failure block:
NSLocalizedDescription=Request failed: unacceptable content-type: text/plain}
Then i added text/plain in this way:
var set = manager.responseSerializer.acceptableContentTypes
set.insert("text/plain")
manager.responseSerializer.acceptableContentTypes = set
right now the types are:
manager.responseSerializer.acceptableContentTypes
[application/json, text/javascript, text/plain, text/json]
But i got the new error:
{ URL: http://192.168.1.9:8081/sec.jsp } { status code: 200, headers {
"Content-Length" = 44;
"Content-Type" = "text/plain; charset=utf-8";
Expires = "Thu, 01 Jan 1970 00:00:00 GMT";
Server = "Jetty(6.1.10)";
"Set-Cookie" = "JSESSIONID=tapmhct7hanv;Path=/";
} }>, Error Domain=NSCocoaErrorDomain Code=3840 "The operation couldn’t be completed. (Cocoa error 3840.)" (JSON text did not start with array or object and option to allow fragments not set.) UserInfo=0x7fda31fb4a90 {NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.})
I think the question is because JSON can't read the response. But i have set it to text/plain, does it still try to parse the plain text as JSON?
I searched and try a way:
manager.responseSerializer = AFJSONResponseSerializer(readingOptions: NSJSONReadingOptions.AllowFragments)
But the error is:
Error Domain=NSCocoaErrorDomain Code=3840 "The operation couldn’t be completed. (Cocoa error 3840.)" (Garbage at end.) UserInfo=0x7ff4b1790660 {NSDebugDescription=Garbage at end.})
Man, this is what I added in when I config my AFNetworking class and it works fine.
The reason you got that 3840 error, is because your API server returns an integer or even empty stuff, which ios json parser failed.
Can u make sure in swift, the phrase your are using is correct way?
_delegateClient.responseSerializer = [AFJSONResponseSerializer serializerWithReadingOptions:NSJSONReadingAllowFragments];
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
manager.responseSerializer = [AFJSONResponseSerializer
serializerWithReadingOptions:NSJSONReadingAllowFragments];
[manager GET:url parameters:parameters progress:nil
success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSLog(#"request: %#\n", responseObject);
completionBlock(responseObject,nil);
}
failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(#"Error: %#\n", error);
completionBlock(nil,error);
}];
I am considering using AFNetworking in one of my projects. But I have a problem.
Here is the code:
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
// manager.responseSerializer = [AFJSONResponseSerializer serializer];
[manager GET:completeUrlString parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"%#", responseObject);
} failure:nil];
The problem Is the respose object. It is a dictionary with only a value inside. The value is shown to be a NSObject! That should actually be a NSDictionary with several key/value pairs.
Here is the raw json:
{
"signInResponse": {
"userName": "971777771554300",
"duration": 315360000000,
"token": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"userId": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"idleTimeout": 2592000000
}
}
Why does the parser fail? Also I would like to note that the url does not end in ".json" as it is dinamically created.
Another small question: several resposes return json objects where the keys that need to be in the
response dictionary are of the form "#importantKey" or "#key". I remmember that some parsers can't returns such keys in their response, is this a problem for AFNetworking?
if you use alamofire, this little snippet can help, maybe you need to do casting like this :
var innerData = data!["signInResponse"]!!
var innerData2 = innerData[0]
var DataDict = (innerData2 as! NSDictionary) as Dictionary
self.userName = DataDict["userName"]! as! String