0

I am trying to send a body of JSON to a REST API, but it is only reading the first parameter and not recognizing the rest of the JSON at all. I tested mistyping the other parts of the JSON body and I did not get an error like I normally would.

func postRequest(classroomID: String, email: String, vote: String){

    //declare parameter as a dictionary which contains string as key and value combination.
    let parameters = [
            "classroomID": classroomID,
            "LastUpdated": "2020-01-01",
            "TheVoteData"[
                          "Email": email,
                          "TheVote": vote
              ]
     ]

    //create the url with NSURL
    let url = URL(string: "https://www.api-gateway/dynamoDB/resource")!

    //create the session object
    let session = URLSession.shared

    //now create the Request object using the url object
    var request = URLRequest(url: url)
    request.httpMethod = "POST" //set http method as POST

    do {
        request.httpBody = try JSONSerialization.data(withJSONObject: parameters, options: .prettyPrinted) // pass dictionary to data object and set it as request body
    } catch let error {
        print(error.localizedDescription)
    }

    //HTTP Headers
    request.addValue("application/json", forHTTPHeaderField: "Content-Type")
    request.addValue("application/json", forHTTPHeaderField: "Accept")

    //create dataTask using the session object to send data to the server
    let task = session.dataTask(with: request, completionHandler: { data, response, error in

        guard error == nil else {
            completion(nil, error)
            return
        }

        guard let data = data else {
            return
        }

        do {
            //create json object from data
            guard let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String: Any] else {
                return
            }
            print(json)
            completion(json, nil)
        } catch let error {
            print(error.localizedDescription)
        }
    })

    task.resume()
}

This will post classroomID to the database, but not email or vote. I got this method from here: How to make HTTP Post request with JSON body in Swift

Any help is really appreciated!

Edit: I was able to work around my issue by configuring the API Gateway to take input as a simple array instead of an array of dictionaries. Big thanks to all who took the time to help me!!

notnoahkirby
  • 309
  • 6
  • 17
  • Convert the request.httpBody data to a string and print it (and tell us what it is). – Lou Franco May 07 '20 at 00:24
  • Do you have a spec for the API or some code from the server that shows what JSON it's expecting – Lou Franco May 07 '20 at 00:31
  • @LouFranco The only thing I get when i print the request.httpBody data is 132 bytes.. also, the server is expecting { "ClassroomId":"api-test", "LastUpdated":"2020-05-07", "TheVoteData":[ { "Email": "123@abc.com", "Vote": "Got it" } ] } – notnoahkirby May 07 '20 at 14:44

1 Answers1

2

I don't think the JSON data you were providing in parameters was valid (I check using jsonlint.com) Try this:

func postRequest(classroomID: String, email: String, vote: String){

//declare parameter as a dictionary which contains string as key and value combination.
let parameters: [String:Any] = [
        "classroomID": classroomID,
        "LastUpdated": "2020-01-01",
        "TheVoteData":[
                      "Email": email,
                      "TheVote": vote
    ]
 ]

//create the url with NSURL
let url = URL(string: "https://www.api-gateway/dynamoDB/resource")!


//now create the Request object using the url object
var request = URLRequest(url: url)
request.httpMethod = "POST" //set http method as POST

do {
    request.httpBody = try JSONSerialization.data(withJSONObject: parameters, options: .prettyPrinted) // pass dictionary to data object and set it as request body
} catch let error {
    print(error.localizedDescription)
}

//HTTP Headers
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")

let jsonData = try! JSONSerialization.data(withJSONObject: parameters, options: [])
//create dataTask using the session object to send data to the server
 let task = URLSession.shared.uploadTask(with: request, from: jsonData) { data, response, error in
    if let data = data, let dataString = String(data: data, encoding: .utf8) {
        print(dataString)
    }
    //Returns HHTP response if
    if let httpResponse = response as? HTTPURLResponse {
        print(httpResponse.statusCode)
    }
}

task.resume()
}
heyylateef
  • 76
  • 1
  • 10
  • You're right - my json wasnt correct! I tried this out, and I am still getting the same result: classroomid to getting posted in the DB but nothing else is. Another person asked what the server is expecting, and this is it -- { "ClassroomId":"api-test", "LastUpdated":"2020-05-07", "TheVoteData":[ { "Email": "email@email.email", "Vote": "Got it" } ] } -- I wonder if there's a problem since this format is a little different from what it's expecting? – notnoahkirby May 07 '20 at 14:52
  • @JacobBarbush That is true, you have to confirm if you're sending the same type that your server is expecting. For example, you'll get a server error if your model (on the server) is expecting an integer but you're sending a string in your swift code. Also, make sure that your server is expecting a dynamic value. If your server is expecting exactly "email@email.email", it will fail when trying to post any other value/string. – heyylateef May 07 '20 at 17:31