14

I'm trying to write a POST request to my local server, this is my function:

@IBAction func postButtonAction(_ sender: UIButton) {

    guard let url = URL(string:"http://localhost:443/api/message") else {return}
    var request = URLRequest(url: url)
    request.httpMethod = "POST"
    request.addValue("application/json", forHTTPHeaderField: "Content-Type")
    print("POSTED")

    let date : Date = Date()
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
    let dateTime = dateFormatter.string(from: date)

    let newPost = MessageForPost(message: "Hi", timestamp: dateTime, latitude: "1.1", longitude: "2.2")
    let newData = DataForPost(message: newPost)
    let newPackage = PackageForPost(data: newData)

    do {
        let jsonBody = try JSONEncoder().encode(newPackage)
        request.httpBody = jsonBody
        print("jsonBody:",jsonBody)
        let jsonBodyString = String(data: jsonBody, encoding: .utf8)
        print("JSON String : ", jsonBodyString!)
    } catch let err  {
        print("jsonBody Error: ",err)
    }

    let session = URLSession.shared
    let task = session.dataTask(with: request){ (data,response,err) in

        guard let data = data else {return}

        do{
            let sendPost = try JSONDecoder().decode(PackageForPost.self, from: data)
            print("DATA:\(data)")
        }catch let err{

            print("Session Error: ",err)
        }
    }
    task.resume()
}

These are the structs using here:

struct PackageForPost:Encodable, Decodable{
    let data: DataForPost
}

struct DataForPost:Encodable, Decodable{
    let message: MessageForPost
}

struct MessageForPost:Codable {
    let message: String
    let timestamp: String
    let latitude: String
    let longitude: String
}

And it was able to print

JSON String :  {"data":{"message":{"message":"Hi","timestamp":"2017-10-18 00:50:13","latitude":"1.1","longitude":"2.2"}}}

But it keeps showing this ERROR:

Session Error: dataCorrupted(Swift.DecodingError.Context(codingPath: [], debugDescription: "The given data was not valid JSON.", underlyingError: Optional(Error Domain=NSCocoaErrorDomain Code=3840 "JSON text did not start with array or object and option to allow fragments not set." UserInfo={NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.})))

Why is it not a valid JSON???

Here's my server's API POST request document:

POST
/api/message

{
    data: {
        message: {

            message: “Hey, a new message!”,
            timestamp: 2017-09-10 10:22:33,
            latitude: 62.233589156441724,
            longitude: 25.735066461654696
        }
   } 
}

I've done quite some googling but am stuck here for a very long time! Any help appreciated!

Zouhair Sassi
  • 1,403
  • 1
  • 13
  • 30
Kei
  • 611
  • 2
  • 11
  • 24
  • I ran you basic decoding code in Playground and it works fine. I might suggest that you decode the `Data` to a `String` and print it just to make sure you know exactly what your trying to decode, because if it starts with `POST`, then that's your problem – MadProgrammer Oct 18 '17 at 08:17
  • 1
    Print the received data: `print(data as NSData)` before the `decode` line . The first byte must be `7B`. The error message says, it isn't. – vadian Oct 18 '17 at 08:28
  • 3
    What @vadian said. You've framed the question as though you believe there is something wrong with the way you construct the data. There isn't. The error message you get is actually one from *decoding* a JSON string to Swift objects. When it says the text must start with an array or object, it means the string must start with either `[` or `{` respectively. Probably the response from the server is not JSON – JeremyP Oct 18 '17 at 09:02
  • It does not start with POST so I guess that not the problem... but thank you anyway! & other thanks for editing my question format! @MadProgrammer – Kei Oct 18 '17 at 16:00
  • It starts with `<3c21444f` and ends with a `>` too, does those counts as brackets? @vadian – Kei Oct 18 '17 at 16:02
  • RIGHT...! After I confirmed with the service guy, "The response to a successful POST request is simply a `'200 OK'` status code", which means it's not even a json object!. Is there a possible way I can parse that ?! – Kei Oct 18 '17 at 16:04
  • The string starts with `"<!DO...`, so it's clearly not JSON – vadian Oct 18 '17 at 16:05
  • OK...stupid question though...Is that string what I sent to server... or the server's response? @vadian – Kei Oct 18 '17 at 16:08
  • The error message is related to the string starting with `Session Error` so it's the server response – vadian Oct 18 '17 at 16:17
  • Thanks! So can I handle that in anyways if that's not a JSON object? The service engineer said that it's only going to return `200 OK` status code – Kei Oct 18 '17 at 16:33

1 Answers1

4

It was simple... I had the same kind of issue.

Look your Struct is Decoding and Encoding Timestamp, latitude and longitude as Strings and JSON is in Double or Floating type.

struct MessageForPost:Codable {
    let message: String
    let timestamp: String
    let latitude: String
    let longitude: String
}

And here JSON

{
    data: {
        message: {
            message: "Hey, a new message!",
            timestamp: 2017-09-10 10:22:33,
            latitude: 62.233589156441724,
            longitude: 25.735066461654696
        }
   } 
}

.... I fixed it at my end and... it worked...

Edited use the same data type...

Ahmadreza
  • 6,950
  • 5
  • 50
  • 69
MFarooqi
  • 1,004
  • 5
  • 12
  • 26