Search code examples
jsonswiftalamofireswifty-json

Error "Garbage at end" when serializing valid JSON data with Alamofire


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?


Solution

  • 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.