error while doing JSON serialization, data not in the correct format

时间:2017-12-18 07:03:04

标签: ios swift

I am trying to upload profile picture to the server. but I got an error while doing JSON Serialization.

the error message in the log are :

[Generic] Creating an image format with an unknown type is an error,

The data couldn’t be read because it isn’t in the correct format

The image appears in the user interface after selecting an image from photo library, but The image is not successfully uploaded to server, so maybe that is why I have error while doing JSON serialization. but i don't know why it is said not in the correct format since i try to upload an image in jpeg format.

here is the simplified code. what went wrong? :(

import UIKit

class HomepageVC: UIViewController, UINavigationControllerDelegate, UIImagePickerControllerDelegate {




    @IBAction func editProfilePictureButtonDidPressed(_ sender: Any) {

        // users choose photo from library or camera


        let imagePickerController = UIImagePickerController()
        imagePickerController.delegate = self
        imagePickerController.allowsEditing = true



        let actionSheet = UIAlertController(title: "Photo Source", message: "please choose your source", preferredStyle: .actionSheet)


        // action camera
        let actionCamera = UIAlertAction(title: "Camera", style: .default) { (action) in

            if UIImagePickerController.isSourceTypeAvailable(.camera) {
                imagePickerController.sourceType = .camera
                self.present(imagePickerController, animated: true, completion: nil)

            } else {
                self.showAlert(alertTitle: "Opppss", alertMessage: "camera can't be used / not available", actionTitle: "OK")
                print("camera can't be used / not available")
            }

        }


        // action photo library
        let actionPhotoLibrary = UIAlertAction(title: "Photo Library", style: .default) { (action) in
            imagePickerController.sourceType = .photoLibrary
            self.present(imagePickerController, animated: true, completion: nil)
        }


        //action cancel
        let actionCancel = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)


        actionSheet.addAction(actionCamera)
        actionSheet.addAction(actionPhotoLibrary)
        actionSheet.addAction(actionCancel)


        self.present(actionSheet, animated: true, completion: nil)



    }






    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {


        let image = info[UIImagePickerControllerOriginalImage] as! UIImage
        avatarImage.image = image
        picker.dismiss(animated: true, completion: nil)



        // call func of uploading file to PHP server
        uploadAvatar()

    }




    func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
        picker.dismiss(animated: true, completion: nil)
    }






    // custom HTTP request body to upload image file
    func createBodyWithParams(_ parameters: [String: String]?, filePathKey: String?, imageDataKey: Data, boundary: String) -> Data {

        var body = Data();

        if parameters != nil {
            for (key, value) in parameters! {
                body.appendString("--\(boundary)\r\n")
                body.appendString("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n")
                body.appendString("\(value)\r\n")
            }
        }

        // kita set agar image yang di upload kemudian berformat .jpg
        let filename = "avatar.jpg"

        let mimetype = "image/jpg"

        body.appendString("--\(boundary)\r\n")
        body.appendString("Content-Disposition: form-data; name=\"\(filePathKey!)\"; filename=\"\(filename)\"\r\n")
        body.appendString("Content-Type: \(mimetype)\r\n\r\n")
        body.append(imageDataKey)
        body.appendString("\r\n")

        body.appendString("--\(boundary)--\r\n")

        return body as Data

    }


    // uploading image to server
    func uploadAvatar() {



        // get ID from Default variable
        let id = userInfo!["id"] as! String


        let url = URL(string: "http://localhost/Twitter/uploadAvatar.php")!
        var request = URLRequest(url: url)
        request.httpMethod = "POST"


        let param = ["id" : id]

        let boundary = "Boundary-\(UUID().uuidString)"
        request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")


        let imageData = UIImageJPEGRepresentation(avatarImage.image!, 0.5)

        // if not compressed, return ... do not continue to code
        if imageData == nil {
            return
        }





        // constructing http body
        request.httpBody = createBodyWithParams(param, filePathKey: "file", imageDataKey: imageData!, boundary: boundary)


        // launc session
        URLSession.shared.dataTask(with: request) { data, response, error in


            DispatchQueue.main.async(execute: {

                if error == nil {

                 // if error is nil, then show message from server





                    do {
                        // json containes $returnArray from php
                        let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary

                        // declare new parseJSON to store json
                        guard let parsedJSON = json else {
                            print("Error while parsing")
                            return
                        }

                        // get id from $returnArray["id"] in PHP - parseJSON["id"]
                        let id = parsedJSON["id"]

                        // successfully uploaded
                        if id != nil {

                            // save user information from Server
                            UserDefaults.standard.set(parsedJSON, forKey: "parsedJSON")


                            // if no ID from server then show the message from server
                        } else {

                            // get main queue to communicate back to user
                            DispatchQueue.main.async(execute: {
                                let message = parsedJSON["message"] as! String
                                self.showAlert(alertTitle: "opppps", alertMessage: message, actionTitle: "OK")
                            })

                        }



                        // error doing JSON serialization
                    } catch {

                        // get main queue to communicate back to user
                        DispatchQueue.main.async(execute: {
                            let message = error.localizedDescription
                            self.showAlert(alertTitle: "Sorry", alertMessage: message, actionTitle: "OK")
                        })

                    }

                    // error ketika koneksi ke server
                } else {

                    // get main queue to communicate back to user
                    DispatchQueue.main.async(execute: {
                        let message = error!.localizedDescription
                        self.showAlert(alertTitle: "oppps", alertMessage: message, actionTitle: "OK")
                    })

                }


            })

            }.resume()


    }


}



// extend data
extension Data {

    mutating func appendString(_ string : String) {

        let data = string.data(using: String.Encoding.utf8, allowLossyConversion: true)
        append(data!)

    }

}

1 个答案:

答案 0 :(得分:1)

Your server data is print for more details. like server error or any other details.

URLSession.shared.dataTask(with: request) { data, response, error in
    DispatchQueue.main.async(execute: {

        // server data is convert in to string and print it
        let strData = String.init(data: data!, encoding: String.Encoding.utf8)
        print(strData )
    })
}

The response returned by the server is not in the JSON format. You can use the tool to test the request first.

Print out of the error code is not a HTTP error code, because of the failure to resolve JSON