0

I am trying to collect data from user and send it to an web service, however I get an error "invalid top-level type in JSON write" I am collecting the steps from the healthstore in another function and all the data is passed into the userhealthprofile variables correctly as it works printing them out. However something is wrong with my JSON code

Full error message is

2017-10-17 09:30:57.170950+0200 IphoneReader[347:40755] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** +[NSJSONSerialization dataWithJSONObject:options:error:]: Invalid top-level type in JSON write'
*** First throw call stack:
(0x1d0b3b3d 0x1c33b067 0x1d0b3a85 0x1da763c1 0x9aa50 0x9bb60 0x2231a3b5 0x2231a349 0x22304979 0x22321f87 0x2286bf1b 0x22868833 0x22868423 0x22867849 0x223146f5 0x222e62bb 0x22a797f7 0x22a7419b 0x22a7457d 0x1d06ffdd 0x1d06fb05 0x1d06df51 0x1cfc11af 0x1cfc0fd1 0x1e76bb41 0x22349a53 0xa4d18 0x1c7ae4eb)
libc++abi.dylib: terminating with uncaught exception of type NSException

Code

@IBAction func submitAction(sender: AnyObject) {

    userHealthProfile.name = nameLabel.text
    print(userHealthProfile.name)

    userHealthProfile.age = Int(ageLabel.text!)
    print(userHealthProfile.age)

    userHealthProfile.heightInMeters = Int(heightLabel.text!)
    print(userHealthProfile.heightInMeters)

    userHealthProfile.weightInKilograms = Int(weightLabel.text!)
    print(userHealthProfile.weightInKilograms)

    for element in stepy.step {
        print(element)
    }

    userHealthProfile.totalStepsCount = stepy.step

    print("pressing button")

    //create the url with URL
    let url = URL(string: "www.thisismylink.com/postName.php")! 
    //change the url

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

    //now create the URLRequest 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: userHealthProfile, options: .prettyPrinted) // pass dictionary to nsdata object and set it as request body
    } catch let error {
        print(error.localizedDescription)
    }

    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 as URLRequest, completionHandler: { data, response, error in

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

This is what userprofile looks like, this is what I need to send as a jsonobject for my web service.

class UserHealthProfile {

    var name: String?
    var age: Int?
    var totalStepsCount: Array<Any>!
    var heightInMeters: Int?
    var weightInKilograms: Int?

}
12
  • Add the error you are getting... Commented Oct 17, 2017 at 8:58
  • Added full error Commented Oct 17, 2017 at 9:08
  • Looks like userHealthProfile is not a [[String:Any]] or [String:Any] Commented Oct 17, 2017 at 10:34
  • Show us the json that is being returned...you can add this before the do try catch print(String(data: data, encoding: .utf8) and copy and paste JSON you get from the server here and then we will be able to help... Commented Oct 17, 2017 at 10:43
  • 1
    You create it yourself according to the documentation of your web API. Commented Oct 17, 2017 at 11:37

1 Answer 1

0

I think you should use Alamofire for calling web API.. Here is the sample code according to your requirements.

I hope this will help you...

func Submit(parametersToSend:NSDictionary)
{


Alamofire.request(.POST, "http://www.thisismylink.com/postName.php",parameters: parametersToSend as? [String : AnyObject], encoding: .URL).responseJSON
    {
        response in switch response.2
        {
        case .Success(let JSON):
            print(JSON)
            let response = JSON as! NSDictionary
            print("My Web Api Response: \(response)")
            break
        case .Failure(let error):
            print("Request failed with error: \(error)")
            break
        }

     }

}

Function Calling in your @IBAction func submitAction(sender: AnyObject) like this

@IBAction func submitAction(sender: AnyObject) {

let steps  = stepy.step
let name = nameLabel.text!
let age = Int(ageLabel.text!)
let height = Int(heightLabel.text!)
let weight = Int(weightLabel.text!)
let parameters = [
      "name": name
      "age": age
      "totalStepsCount": steps
      "heightInMeters": height
      "weightInKilograms": weight
       ]
 self.submit(parametersToSend:parameters)

}
Sign up to request clarification or add additional context in comments.

8 Comments

This is really awesome and really simplified the code I needed. I'm not originally a swift programmer but had to switch to swift because the health kit code wouldn't work in C# xamarin, so thanks, will try this out.
I get an error on this part of the code Alamofire.request(.POST, "thisismylink.com/postName.php",parameters: parametersToSend as? [String : AnyObject], encoding: .URL).responseJSON Says "thisismylink.com/postName.php" is an extra argument in call.
your are using swift 3 or swift 4?
Apparently Swift 4
Alamofire Version?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.