Serializing and decoding JSON in Swift - json

I was converting JSON from data when I received an error:
'NSInvalidArgumentException', reason: '*** +[NSJSONSerialization dataWithJSONObject:options:error:]: Invalid top-level type in JSON write'
The data was printed as expected, but the JSON wasn't. I think the code failed in the first line after the do statement.
do {
var str: String = "http://localhost:5000/requirements/\(Array.joined(separator: "_"))"
let url = URL(string: str)
URLSession.shared.dataTask(with: url!) { (data, response, error) in
guard let data = data else { return }
print(data)
do {
let json = try? JSONSerialization.data(withJSONObject: data)
print(json)
if let json = json {
print(json)
let decodedList = try? JSONDecoder().decode(List.self, from: json)
print(decodedList)
if let items = decodedList {
listToDisplay = items.itemsAsString.components(separatedBy: ",")
print(listToDisplay)
}
}
} catch let jsonErr {
print("Error serializing json", jsonErr)
}
}.resume()
return listToDisplay
}

Related

Getting error when assigning JSON array value to variable

I would like to assign a value from JSON to a variable, the issue is Swift thinks I am passing an entire array and not just the JSON value of code to the variable.
I have the following structure and JSON decode function:
private func JSONFunction() {
guard let url = URL(string: "https://example.com/example/example"),
let nameValue = stringValue.addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed)
else { return }
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = "name=\(nameValue)".data(using: .utf8)
URLSession.shared.dataTask(with: request) { data, _, error in
guard let data = data else { return }
do {
let myData = try JSONDecoder().decode(codeStruct.self, from:data)
DispatchQueue.main.async {
codeNum = myData.code
print(codeNum)
}
}
catch {
print(error)
}
}.resume()
}
The following is the structure for decoding the JSON:
struct codeStruct: Codable {
let code: String
let line: String
let person: String
let maker: String
}
Error received:
typeMismatch(Swift.Dictionary,
Swift.DecodingError.Context(codingPath: [], debugDescription:
"Expected to decode Dictionary but found an array
instead.", underlyingError: nil))
Without looking at the json, if I were to guess, I would say that your incoming JSON is actually an array of codeStruct objects, for which you should change your line to
let myData = try JSONDecoder().decode([codeStruct].self, from:data)

Importing Firebase causes JSON fetching ambiguous

I have been fetching JSON in my View Controller, and I needed a function to add data in that same VC to firebase, so imported Firebase ( Pods firebase core, auth and firestore ) and now it gives me an error on JSON fetching that it's Ambiguous use of 'subscript'
func getDetails(link: URL!) {
var plot : String = " "
let task = URLSession.shared.dataTask(with: link!) { (data, response, error) in
if error != nil
{
print("error")
}
else
{
if let content = data
{
do
{
//JSON results
let myJson = try JSONSerialization.jsonObject(with: content, options: JSONSerialization.ReadingOptions.mutableLeaves) as AnyObject
//myJson ~~~ ["Plot"] Ambiguous use of 'subscript'
plot = myJson["Plot"] as! String
}
catch
{
print("error in JSONSerialization")
}
}
}
}
task.resume()
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, execute: {
self.plot.text = plot
})
}
I would love to maintain ability to pick the "Plot" value of JSON and have the firebase running
Your problem is casting result from JSONSerialization to AnyObject. If you want to be able to use subscript, you should, in your case, downcast result to dictionary type, for example [String:Any]
if let myJson = try JSONSerialization.jsonObject(with: content, options: .mutableLeaves) as? [String:Any] {
// plot = myJson["Plot"] as? String ?? "Default value"
}
Anyway, rather learn something about Codable and use it instead of JSONSerialization. Just create class/struct conforming to Decodable protocol and then use JSONDecoder to decode Data object.
Here's how I would rewrite this method, given a ModelObject struct or class that represents your server response.
func getDetails(link: URL!) {
var plot = " "
let group = DispatchGroup()
group.enter()
let task = URLSession.shared.dataTask(with: link!) { (data, response, error) in
defer { group.leave() }
guard error == nil else {
print(error)
return
}
if let content = data {
do {
let modelObject = try JSONDecoder().decode(ModelObject.self, from: data)
plot = modelObject.plotString
}
catch {
print(error)
}
}
}
task.resume()
group.notify(queue: DispatchQueue.main) {
self.plot.text = plot
}
}

Cannot convert JSON Data in Swift 3

I'm converting a project from Obj-c to Swift 3 and I can't get it to read JSON responses from our web methods. As far as I can see, the code looks like a good conversion from it's Obj-c counterpart, but the JSONSerilaization is having trouble.
I would post the old Obj-c, but it's spread across several NSURLConnection delegate methods. I can post this if required?
Swift 3:
// Set up the URL request
var getString : String = "https://TheWebMethod"
guard let url = URL(string: getString) else {
print("Error: cannot create URL")
return
}
let urlRequest = URLRequest(url: url)
// set up the session
let config = URLSessionConfiguration.default
let session = URLSession(configuration: config)
// make the request
let task = session.dataTask(with: urlRequest) {
(data, response, error) in
// check for any errors
guard error == nil else {
print("error calling GET on Method")
print(error)
return
}
// make sure we got data
guard let responseData = data else {
print("Error: did not receive data")
return
}
// parse the result as JSON, since that's what the API provides
do {
guard let result = try JSONSerialization.jsonObject(with: responseData, options: []) as? [String: AnyObject] else {
print("error trying to convert data to JSON")
return
}
print("The result is: " + result.description)
guard let resultTitle = result["title"] as? String else {
print("Could not get title from JSON")
return
}
print("The title is: " + resultTitle)
} catch {
print("error trying to convert data to JSON")
return
}
}
task.resume()
Example JSON output when run through browser:
[{"id":"3","Initials":"TL","FullName":"Tony Law","LoginName":"test","Password":"password","EmailAddress":"myemailaddress","MobileTelNo":"0123456789","SecToken":"Secret"}]

JSON parsing using Swift

I have a php file which create a JSON array. This the JSON output.
[{"employee_id":"1","employee_name":"Steve","employee_designation":"VP","employee_salary":"60000"},{"employee_id":"2","employee_name":"Robert","employee_designation":"Executive","employee_salary":"20000"},{"employee_id":"3","employee_name":"Luci","employee_designation":"Manager","employee_salary":"40000"},{"employee_id":"4","employee_name":"Joe","employee_designation":"Executive","employee_salary":"25000"},{"employee_id":"5","employee_name":"Julia","employee_designation":"Trainee","employee_salary":"10000"}]
I want to parse this array using swift in my app. So I used the following code to parse the JSON array
func jsonParser() {
let urlPath = "xxxxxxxxx/dbretrieve.php"
guard let endpoint = NSURL(string: urlPath) else { print("Error creating endpoint");return }
let request = NSMutableURLRequest(URL:endpoint)
NSURLSession.sharedSession().dataTaskWithRequest(request) { (data, response, error) -> Void in
do {
guard let dat = data else { throw JSONError.NoData }
guard let json = try NSJSONSerialization.JSONObjectWithData(dat, options:.AllowFragments) as? NSArray else { throw JSONError.ConversionFailed }
print(json)
} catch let error as JSONError {
print(error.rawValue)
} catch {
print(error)
}
}.resume()
}
but I get the following error
Error Domain=NSCocoaErrorDomain Code=3840 "Invalid value around character 0." UserInfo={NSDebugDescription=Invalid value around character 0.}
What's the mistake I made?
I checked your json array. Its perfect.
The point where the issue might be serialization.
Depends on data you get in response
Try to disable debugging mode in PHP
Try below serialisation code
Sample Code:
do {
let json = try NSJSONSerialization.JSONObjectWithData(data, options: []) as! [String: AnyObject]
print(json)
} catch let error as NSError {
print("Failed to load: \(error.localizedDescription)")
}

Unable to parse JSON from the HTTP response

Why am I unable to parse JSON from the HTTP response via the following code?
if let url = NSURL(string: "https://2ch.hk/b/threads.json") {
let task = NSURLSession.sharedSession().dataTaskWithURL(url) {
(data, response, error) in
var jsonError: NSError?
let jsonDict = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: &jsonError) as [String: AnyObject]
if jsonError != nil {
return
}
// ...
}
task.resume()
}
Output
fatal error: unexpectedly found nil while unwrapping an Optional value
What am I doing wrong? How can I fix it?
Thanks in advance.
This is a bit late.... but I think you are trying to parse the error as well so add an else part and and the dictionary to be serialized will only be parsed if there is the data ... your code can be modified as follows
if let url = NSURL(string: "https://2ch.hk/b/threads.json") {
let task = NSURLSession.sharedSession().dataTaskWithURL(url) {
(data, response, error) in
if (jsonError != nil) {
return
} else {
var jsonError: NSError?
let jsonDict = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: &jsonError) as [String: AnyObject]}
// ...
}
task.resume()
}