0

My code return a Code=3840 "Garbage at end." when I try to keep my data of a request to my api ... The JSON return is a Valid JSON accorded to jsonlint (tested with Postman):

{
    "error": 0,
    "message": "transaction_completed"
}

this is my code :

func request(urle : url, parameters : Parameters, completion: @escaping (JSON) -> Void)
{
    Alamofire.request(getUrl(urlw: urle), method: .post, parameters: parameters).responseJSON
    {
        response in
        if response.data != nil {
            do{
                let json = try JSON(data: response.data!)
                completion(json)
            }catch{
                print(error)
            }
        }
    }
}

and this is when I called the request function:

let parameters: Parameters=[
    "key" : user.key,
    "uid": user.id
]
api.request(urle: .buyStack, parameters: parameters) { json in
    print(json)
}

Where did I go wrong?

halfer
  • 19,824
  • 17
  • 99
  • 186
Louis Brahmi
  • 834
  • 2
  • 9
  • 21
  • Could you do `print("data: \(response.data as NSData)")`? I'm wondering if there is not a invisible character that might be allowed by POSTMAN. – Larme Oct 23 '18 at 08:29
  • @Larme Thanks to your reply, when I paste your code : `'Data?' is not convertible to 'NSData'; did you mean to use 'as!' to force downcast?` and when i "force the downcast" i have this : data : <7b226572 726f7222 3a312c22 6d657373 61676522 3a22556e 64656669 6e656420 4150494b 6579227d 5b5d> – Louis Brahmi Oct 23 '18 at 08:34
  • Yes. For debug, you can use a force unwrap (well, it's not that critical). But in your code you should have use an `if let`: `if let data = response.data { do { ... JSON(data: data)...}...}` instead of the force unwrap. – Larme Oct 23 '18 at 08:36
  • @Larme Ok yes, so you have an idea how can I show you the response ? – Louis Brahmi Oct 23 '18 at 08:39
  • 1
    You have `{"error":1,"message":"Undefined APIKey"}[]`. It's not an invisible character, you have extra `[]`. Which converts the whole response an invalid JSON. – Larme Oct 23 '18 at 08:42
  • Oh yes thanks!! You have converted the <7b226572 726f7222 3a312c22 6d657373 61676522 3a22556e 64656669 6e656420 4150494b 6579227d 5b5d> ? – Louis Brahmi Oct 23 '18 at 08:44
  • Can you tell me how you convert if I have problem in future ? – Louis Brahmi Oct 23 '18 at 08:45
  • That's what I did. I asked for the `Data` because if it would have been an invisible character, giving already the `String` might not have shown it. But you since it's not, you can do in your code: `let stringResponse = String(data: data, encoding: .utf8)` and print it. But I used a similar solution (in Objective-C because that was my quickest opened project): https://stackoverflow.com/questions/39075043/how-to-convert-data-to-hex-string-in-swift from your "hexdata" (I added the removal of "<", ">" and "spaces" before translating it). It's a good debug tool. – Larme Oct 23 '18 at 08:45

1 Answers1

1

So apparently your JSON is not valid, it has at the end some invalid values.

First thing to do. For the sake of the keeping the logic, you can use force unwrap (using !) because it's debugging. I'm not sure that this code compile, it's just a logic presentation.

let responseString = String(data: response.data, encoding: .utf8)
print("responseString: \(responseString)")

This gives:

{"error":1,"message":"Undefined APIKey"}[]

There is extra [] at the end, and it's then not a valid JSON. You can ask the developper to fix it. If you really can't, or want to continue developing while it's in progress in their side, you can remove the extra [].

You can check this answer to remove the last two characters, and then:

let cleanResponseJSONString = //check the linked answer
let cleanResponseData = cleanResponseJSONString.data(encoding: .utf8)
let json = try JSON(data: cleanResponseData)

Side note and debugging idea if it was more complicate:

I ask for print("data: \(response.data as! NSData)") because this print the hex data. Your issue could have been due to an invisible character at the end. If you don't know them, the least you can do is according to previous answer:

let jsonString = "{\"error\":1,\"message\":\"Undefined APIKey\"}" (that's almost reponseString)
let jsonData = jsonString.data(encoding: .utf8)
print("jsonData: \(jsonData as! NSData)")

And compare what the end looks like.

A debugger tip, you can use a answer like this one to convert hexDataString into Data and debug from it. I'd recommend to add a space, "<" and ">" removal before so you can easily copy/paste it from the debugger output. Why? If it's long (many manipulation) to go where your issue lies (login in the app, certain actions to do etc.), this could save you time to debug it on another app (Playground, at the start of your AppDelegate, etc.).

Don't forget to remove all the debug code afterwards ;)

Not related to the issue:

if response.data != nil {
        do {
            let json = try JSON(data: response.data!)
            ...
        } catch {
        ...
    }
}

Should be:

if let data = response.data {
        do {
            let json = try JSON(data: data)
            ...
        } catch {
        ...
    }
}

Use if let, guard let to unwrap, avoid using force unwrap.

Larme
  • 24,190
  • 6
  • 51
  • 81