0

I need to make post request with my data. Also it takes access_token in header. Now I will describe the complete structure of my post-request in body. I have to send description which takes String. The data to be sent is taken from the descriptionTextView. Photo accepts a file that I upload from imagePicker in photoButton. Rate takes a dictionary. The data is taken from my text fields in rateInputView { "availability": 1, "beauty": 2, purity: 3 } Report_status always accepts the string "Accepted". Type_obj takes a string and depends on what I choose in my pickerView(route, event, place). id_obj takes the id of the object that I save from the searchBar. There should also be a Results field. Here that structure: [{ "waste_id":{"name": "Caps", "unit_of_waste": "piece"}, amount: 10 }] That takes values ​​from the text fields of the wasteInputView as well as the name of the Label in that wasteInputView.

I tried to make it, but i have an error: Failed to parse JSON: Error Domain=NSCocoaErrorDomain Code=3840 "JSON text did not start with array or object and option to allow fragments not set. around line 1, column 0." UserInfo={NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set. around line 1, column 0., NSJSONSerializationErrorIndex=0}

How i can fix it? Here is my code:

@objc func postActionButton() {
        // Check if access token is available
        guard let accessToken = UserDefaults.standard.string(forKey: "AccessToken") else {
            print("Access token is missing")
            return
        }
        
        // Prepare the URL
        guard let url = URL(string: "\(apiLink)/report/create_report/") else {
            print("Invalid URL")
            return
        }
        
        // Prepare the request
        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        
        // Set the access token in the header
        request.setValue("Bearer \(accessToken)", forHTTPHeaderField: "Authorization")
        
        // Prepare the data for the request body
        guard let image = selectedImage else {
            print("No image selected")
            return
        }
        
        guard let imageData = image.jpegData(compressionQuality: 0.8) else {
            print("Failed to convert image to data")
            return
        }
        
        let base64Image = imageData.base64EncodedString()
        
        // Create the request body
            let parameters: [String: Any] = [
                "photo": base64Image,
                "description": descriptionTextView.text ?? "",
                "rate": [
                    "availability": rateInputView.transportTextField.text ?? "",
                    "beauty": rateInputView.beautyTextField.text ?? "",
                    "purity": rateInputView.pollutionTextField.text ?? ""
                ],
                "report_status": "Accepted",
                "type_obj": selectedOption ?? "",
                "id_obj": selectedOptionID ?? 0,
                "Results": [
                    [
                        "waste_id": [
                            "name": wasteInputView.wasteLabel.text ?? "",
                            "unit_of_waste": "kg"
                        ],
                        "amount": wasteInputView.bulbTextField.text ?? ""
                    ] as [String : Any]
                ]
            ]
            
            do {
                request.httpBody = try JSONSerialization.data(withJSONObject: parameters, options: [])
            } catch {
                print("Failed to create JSON data: \(error)")
                return
            }

            let task = URLSession.shared.dataTask(with: request) { data, response, error in
                if let error = error {
                    print("Request error: \(error)")
                    return
                }

                guard let data = data else {
                    print("No data received")
                    return
                }

                do {
                    if let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] {
                        // Process the response JSON
                        print("Response JSON: \(json)")
                    }
                } catch {
                    print("Failed to parse JSON: \(error)")
                }
            }

            task.resume()
    }

Here's stucture in postman: enter image description here enter image description here

  • 1
    `print("Response str: \(String(data: data, encoding: .utf8)")` to see what you are actually receiving. Could be an error message, or just other format response, because you didn't put that you wanted JSON in the accept header – Larme Jun 09 '23 at 11:58
  • @Larme server is returning an HTML response instead of the expected JSON response – Alexander Chebotarev Jun 09 '23 at 13:14
  • I think you need to ask yours server why it sends HTML instead of JSON. – Cy-4AH Jun 09 '23 at 14:17
  • "@Larme server is returning an HTML response instead of the expected JSON response – " "Expected JSON": Is that really what the doc says? Also, did you read the HTML? Some times the response is in HTML, but you get in text there "Bad URL", "Bad parameter", etc. Read it just in case. Your API maybe expect you do add `request.addValue("application/json", forHTTPHeaderField: "Accept")`, ie: responds to me in JSON. – Larme Jun 09 '23 at 14:53
  • @Larme Exception Type: MultiValueDictKeyError – Alexander Chebotarev Jun 09 '23 at 16:18
  • I guess your parameter is wrong then, but we don't know the full doc of the API. – Larme Jun 09 '23 at 16:21
  • @Larme I've updated the question, added what it looks like in postman – Alexander Chebotarev Jun 09 '23 at 16:32
  • 1
    So you should use "multiform part data", look for that. You can ask Postman to generate Swift code, you'll see how the body looks like. – Larme Jun 09 '23 at 16:34
  • @Larme thx so much, didn't know about swift generator in postman, now it works well – Alexander Chebotarev Jun 09 '23 at 16:52

0 Answers0