alamofire.error Code=-6006 "JSON could not be serialized - json

Been working on this for a bit with no success. I have a function that goes to a UIButton solely to perform alamofire calls to my rails api which uses all JSON.
I'm using Swift 2, Alamofire 3, XCode 7 & Rails 4 for my api which is deployed to Heroku
I keep getting this error when I fire off the function :
alamofire.error Code=-6006 "JSON could not be serialized. Input data was nil or zero length.
Here is my code :
#IBAction func Save(sender: AnyObject) {
let postsEndpoint: String = "https://APIURL"
let parameters = [
"users": [
"name": "James McHarty",
"avatar": "Some binary data",
"post": [
"title": "First Test Post",
"body": "This is the first test post for the API",
"liked": "8", //will make INT later
"img": "more binary data"
]
]
]
Alamofire.request(.POST, postsEndpoint, parameters: parameters, encoding: .JSON)
.responseJSON { response in
guard response.result.error == nil else {
// got an error in getting the data, need to handle it
print(response.result.error!)
return
}
}
print("func'd")
}

This is not Alamofire or swift error, The response returned by the server is not in the JSON format. you can print out response data and check what is wrong in this.
try this code to print out our server data to easily identifying to error and resolve this.
Alamofire.request("Your url").responseJSON(completionHandler: { (response) in
switch response.result {
case .success(let value):
break
case .failure(let error):
print("\n\n===========Error===========")
print("Error Code: \(error._code)")
print("Error Messsage: \(error.localizedDescription)")
if let data = response.data, let str = String(data: data, encoding: String.Encoding.utf8){
print("Server Error: " + str)
}
debugPrint(error as Any)
print("===========================\n\n")
}
})

The response returned by the server is not in the JSON format. You can use the tool to test the request first.
Print out of the error code is not a HTTP error code, because of the failure to resolve JSON

You need to check the mimeType it will be "text/plain" instead of "application/json". That's why JSONSerialization class not able to parse the data.

Related

Alamofire.AFError.ResponseSerializationFailureReason.jsonSerializationFailed

I'm trying to decode json from google drive attachment but it shows the following error:
responseSerializationFailed(reason: Alamofire.AFError.ResponseSerializationFailureReason.jsonSerializationFailed(error: Error Domain=NSCocoaErrorDomain Code=3840 "Invalid value around character 0." UserInfo={NSDebugDescription=Invalid value around character 0.}))
The JSON:
{
"price" : 5000,
"item" : "Some item"
}
Models:
struct Things: Codable {
let price: Int,
let item: String
}
Request:
Alamofire.request("https://drive.google.com/linkhere").responseJSON { (response) in
switch response.result {
case .failure(let error):
print("error : \(error)")
case .success:
print("success!")
let decoder = JSONDecoder()
let things = try! decoder.decode(Things.self, from: response.data!)
print("things.price : \(things.price)")
print("things.item : \(things.item)")
}
}
This only occurs when i fetch json from google drive attachment (the json is valid).
Are there any difference when fetching json from google drive attachment?
If your response goes in failure case that means api call is having an issue, if your response goes in success state that means it may chances your decoding have some issue.
Failure case:
Check api in postman
Check api method(i.e GET or POST)
Check encoding or content type "application/json"

Cannot force unwrap value of non-optional type but prints with "optional"

First off before anybody puts a cheeky "duplicate question" post. I have gone through EVERY single one on stack and then some. The similar posts have either been inapplicable or haven't worked for me.
Background:
I am trying to build an app to communicate with a website (server down the road, one step at a time.) I have established communication and verified that it works. Long and the short of it, the data coming in when printed has an "optional" in front of it.
My website is very barebones and is made up of an html and js file. The js is linked to my html via <"script"> command. I am trying to us a JSONdecode in swift but am prompted with a "not valid JSON" error. When I investigated further I am getting the previously mentioned "optional" in my data. I tried using "!" to force unwrap my incoming data but am prompted with "cannot force unwrap value of non-optional type"??? When I try my swift code with a known JSON website (something I found on youtube) it works fine.
Obviously my question isn't exclusive to "force unwrap." The solution provided may change what is necessary to rectify this ie. change what the question "should have been." I am open to any and all solutions but maybe we'll just start with how can I force unwrap this?
Thank you in advance.
XCODE (Swift)
super.viewDidLoad()
let url = URL(string: "https://*****for my eyes only*****.com/script.js")!
var request = URLRequest(url: url)
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.httpMethod = "POST"
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data,
let response = response as? HTTPURLResponse,
error == nil else
{
print("error", error ?? "Unknown error")
return
}
guard (200 ... 299) ~= response.statusCode else
{
print("statusCode should be 2xx, but is \(response.statusCode)")
print("response = \(response)")
return
}
//shows data printed w/ optional in front of data
let htmlcontent = NSString(data: data, encoding: String.Encoding.utf8.rawValue)
print(htmlcontent)
//data is the portion I am trying to force unwrap
//currently produces error "not valid JSON"
let decoder = JSONDecoder()
let classes = try! decoder.decode([Class].self, from: data)
HTML Code
<html>
<body>
<script src="script.js"></script>
</body>
</html>
JS Code (Taken from internet - Not Mine)
{
"mothmap": {
"value": [
{
"longitude": -0.13025200000004133,
"latitude": 51.4596619
},
{
"longitude": -2.707384100000013,
"latitude": 53.7613383
}
]
}
}
The error says
Expected to decode Array but found a dictionary instead.
This is true. Your JSON is not an array, but you passed an array type [Class] to the decoder. You need to match the type to the JSON.
Try
let classes = try! decoder.decode(Class.self, from: data)
Or edit the JSON to put the class in []
[{
"mothmap": {
"value": [
{
"longitude": -0.13025200000004133,
"latitude": 51.4596619
},
{
"longitude": -2.707384100000013,
"latitude": 53.7613383
}
]
}
}]

How to send json body in get request

I know sending json body in get request is violating http rules, however according to client's requirement the server is accepting json body in get request.so i want to send json body in my get request using alamofire.
i tried various parameter encoding types.nothing worked.
func listNews( withCompletionHandler:#escaping (_ status:Bool, _ message: String, _ yearLevels: JSON) -> Void){
let parameters = [
"month": "07",
"year": "2019",
"record_start": 0,
"record_offset": 100
] as [String : Any]
let headers = [
"Content-Type": "application/json"
]
let url = STAFF_SERVICE_URL+"staff/2/news?api_key=\(api_key)"
print("URL > \(url)")
Alamofire.request(url, method: .get,parameters:parameters, encoding: JSONEncoding.default, headers: headers).responseJSON { (response) in
let statusCode = response.response?.statusCode
print(statusCode ?? "Success Error Code")
if(statusCode==200){
let swiftyJsonVar = JSON(response.result.value!)
print(swiftyJsonVar)
withCompletionHandler(true,"Success",swiftyJsonVar)
}else if(statusCode==400){
withCompletionHandler(false,"System Error. Please try again later.",JSON.null)
}else{
withCompletionHandler(false,"System Error",JSON.null)
}
}
}
i expect array of json objects in response. but the actual output is time out error
Actually you should change encoding method for get request. You have set encoding: JSONEncoding.default. Instead of that, use encoding: URLEncoding.default.
Second thing, if you are sending parameters in json body, then send all parameters instead of some sending with body and some in url. So, your api_key=\(api_key) should be in json body.
I hope this will fix your issue.

Parsing JSON data with Gloss and Alamofire in swift

I trying to decode an json object from a webrequest with Swift 3, Gloss 1.1 and Alamofire 4.0:
The json response looks like this:
{
"code": "0",
"message": "OK.",
"data": [
{
"timestamp": 1480885860,
"open": 10.99
},
{
"timestamp": 1480886040,
"open": 11
}
]
}
My json Decodables are the following two:
struct ResponseJsonModel : Decodable {
let code : Int
let message : String
let data : [MarketPriceJsonModel]?
// <~~
init?(json: JSON) {
guard let codeInt : Int = "code" <~~ json else {
print("code unwrapping failed in guard")
return nil
}
guard let messageStr : String = "message" <~~ json else {
print("message unwrapping failed in guard")
return nil
}
self.code = codeInt
self.message = messageStr
self.data = "data" <~~ json
}
}
struct MarketPriceJsonModel : Decodable {
let timestamp : NSDate
let open : Double
init?(json: JSON) {
guard let timestampInt : Int = "timestamp" <~~ json else {
print("timestamp unwrapping failed in guard")
return nil
}
guard let open : Double = "open" <~~ json else {
print("open price unwrapping failed in guard")
return nil
}
self.timestamp = NSDate(timeIntervalSince1970: Double(timestampInt))
self.open = open
}
}
I'm new to Gloss and don't understand why the initalize of my decodable-Object fails.
Alamofire.request(url).validate().responseJSON { response in
switch response.result {
case .success:
guard let value = response.result.value as? JSON,
let responseModel = ResponseJsonModel(json: value) else {
print("responseModel failed")
return
}
print(responseModel.message)
case .failure(let error):
print(error)
}
}
The output of the code is
code unwrapping failed in guard
responseModel failed
but why?
When I add a breakpoint in init?() and look at the json-variable in the debug area, so the request looks ok but the parsing fails.
Is there a way to get better exception messages in case something fails?
Any input appreciated.
Ok, problem solved. It was a faulty configuration of the webservice.
As you can see, the json response of the code attribute was:
"code": "0",
This format clearly stands for a string, therefor my guard with parsing into Int will fail.
To solve this, there are two possible ways I found.
Option 1: either change json response to:
"code": 0,
(value has no more surrounding quotes). This is probably the best solution as it fixes the wrong datatype of the webservice, but it requires to have full control over the codebase of the service.
Option 2: simply parse the json response into a String and after that, force-unwrap into an Int workes too. For this solution the webservice will remain unchanged.
guard let codeStr : String = "code" <~~ json else {
print("code unwrapping failed in guard")
return nil
}
self.code = Int(codeStr)!

Invalid type in JSON write (_SwiftValue) using Alamofire

I have tried a lot of things now and are still getting:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Invalid type in JSON write (_SwiftValue)'
UPDATE:
I scan a barcode and save the info:
let calendar = Calendar.current
let expiryDate = (calendar as NSCalendar).date(byAdding: .month, value: 3, to: Date(), options: [])?.description
let barcode = BarcodeData(barcodeValue: value,
datetime: dateTime,
expiryDate: expiryDate!,
latitude: latitude.description,
longitude: longitude.description,
status: txtStatus.text!,
type: txtType.text!,
extraText: "")
Object are then mapped to a JSON string, it seems that the slashes (/) are added by this function:
let jsonBarcode = Mapper<BarcodeData>().toJSONString(barcode)
The barcode are then added to a list of String:
barcodeDataList.append(jsonBarcode)
When I click a button I invoke the web service, that anticipate parameters in the form of:
let testParams : Parameters =
[ "udid": "my_udid",
"data": jsonArray
]
jsonArray consist of an array of the BarcodeData-object(s) as seen above.
Communication with the web service looks like:
Alamofire.request(url, method: .post, parameters: testParams, encoding: JSONEncoding.default).validate().responseJSON { response in
switch response.result {
case .success:
print("Validation successful")
if let json = response.result.value {
print("JSON: \(json)")
}
case .failure(let error):
print("Error: \(error)")
}
}
The following is passed to the ws:
["udid": "\"001-my_udid\"", "data": [
"{\"latitude\":\"0.0\",\"status\":\"Empty\",\"datetime\":\"2016-09-20 05:10\",\"longitude\":\"0.0\",\"type\":\"ABC123\",\"barcodevalue\":\"123456\"}"
]]
The json array for "data" validates at jsonlint.com and the response from the server is in the form of a json object like:
{result: "Data successfully received"}
Change your encoding in request from encoding: JSONEncoding.default to encoding: URLEncoding.default
I think you need to encode your array in json object try something like this
do{
let data = try NSJSONSerialization.dataWithJSONObject(mappingArray, options: NSJSONWritingOptions(rawValue: 0))
let mappedString : String = (String(data: data , encoding: NSUTF8StringEncoding)!)
return mappedString
}
catch{
print(error)
return error as! String
}
Append this string with your url