1
votes

I am trying to parse my JSON response coming from rest api but constantly getting an error.

My request sending and JSON parsing code is below and also I added Xcode's error message.

I appreciate any help in advance.

My JSON format:

{
    "error":1,
    "name":"batuhan",
    "mail":"[email protected]",
    "password":"e10adc3949ba59abbe56e057f20f883e",
    "user_type":"user"
}

My code:

@IBAction func registerButton(_ sender: Any) {

    let name: String = self.name.text!
    let mail: String = self.mail.text!
    let password: String = self.password.text!


    var responseString: String = ""

    let url = URL(string: "http://my_webserver/index.php?process=register")!
    var request = URLRequest(url: url)
    request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
    request.httpMethod = "POST"
    let postString = "mail=\(String(describing: mail))&name=\(String(describing: name))&password=\(String(describing: password))&register_type=user"
    request.httpBody = postString.data(using: .utf8)
    let task = URLSession.shared.dataTask(with: request) { data, response, error in
        guard let data = data, error == nil else {                                                 // check for fundamental networking error
            print("error=\(String(describing: error))")
            return
        }

        if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {           // check for http errors
            print("statusCode should be 200, but is \(httpStatus.statusCode)")
            print("response = \(String(describing: response))")
        }

        responseString = String(data: data, encoding: .utf8)!

    }


    struct RegisteredUser: Codable {
        let error: String
        let name: String
        let mail: String
        let password: String
        let user_type: String
    }


    let jsonData = responseString.data(using: .utf8)!
    let decoder = JSONDecoder()
    let user_data = try! decoder.decode(RegisteredUser.self, from: jsonData)

    print(user_data.name)
    print(user_data.mail)


    task.resume()
}

The error:

fatal error: 'try!' expression unexpectedly raised an error: Swift.DecodingError.dataCorrupted(Swift.DecodingError.Context(codingPath: [], debugDescription: "The given data was not valid JSON.", underlyingError: Optional(Error Domain=NSCocoaErrorDomain Code=3840 "No value." UserInfo={NSDebugDescription=No value.}))): file /Library/Caches/com.apple.xbs/Sources/swiftlang/swiftlang-900.0.65/src/swift/stdlib/public/core/ErrorType.swift, line 181

1
If you log jsonData and responseString before you decode, what do you see?Itai Ferber
@ItaiFerber I don't log them, even I put print(responseString) right after the line ----responseString = String(data: data, encoding: .utf8)!---- it doesn't show upbakayim
Which means, then, that your code is never getting hit, and responseString retains its default value of ””, which is why you can’t parse itItai Ferber
"No value", your response is empty? Make usefull prints: At the start of the closure, add: print("Response: (response)"); print("Task Error: (error)"); print("Data: (data); (String(data: data, encoding: .utf8)")`; might be helpful, but I think that you have an error somewhere.Larme

1 Answers

3
votes

Your questions covers the problem a bit too much, it is clearly in the JSON decode which you should have isolated. Anyways: here comes the (trivial) answer.

In your JSON-data erroris a number and in your class definition it is a String.

So you have two very simple paths to solve your problem, either you should define

error: Int

in your RegisteredUser or you put

"error":"1",

into your JSONdata.

If what you showed in the beginning was returned from your web service you will have to adapt the format of your RegisteredUser to match the JSON-data exactly. Remember: JSONDecoder.decode is very picky, as any good parser should be.

I would generally recommend to catch errors like this and not use try! if you are talking to the web since there are simply too many things that can go wrong. Although I have to admit that in this case error.localizedDescription was not terribly helpful at

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

This did however point me in the right direction since it made me read your input more closely.

Update (with code)

I successfully parsed your Stringin a playground as follows:

import Cocoa
struct RegisteredUser: Codable {
    let error: Int
    let name: String
    let mail: String
    let password: String
    let user_type: String
}

var str = """
{
"error":1,
  "name":"batuhan",
  "mail":"[email protected]",
  "password":"e10adc3949ba59abbe56e057f20f883e",
  "user_type":"user"
}
"""
let jsonData = str.data(using: .utf8)!
let decoder = JSONDecoder()

do {
    let user_data = try decoder.decode(RegisteredUser.self, from: jsonData)
    print(user_data)
} catch {
    print("error on decode: \(error.localizedDescription)")
}

This prints

RegisteredUser(error: 1, name: "batuhan", mail: "[email protected]", password: "e10adc3949ba59abbe56e057f20f883e", user_type: "user")

Please post the code that does not work (and what you expect it to do) if you would like us to help you.