Error to parse a JSON file in Swift 3 - json

I´m newbie in Swift and I have some problems with parsing JSON using Swift 3 code.
This is my JSON (extract):
[
{
"COD_USUARIO":"4",
"0":"4",
"USUARIO":"PIEDAD",
"1":"PIEDAD",
"CLAVE":"MU\u00d1OZ",
"2":"MU\u00d1OZ",
"ACTIVO":"1",
"3":"1",
"FECHA_ALTA":"2010-12-07 00:00:00",
"4":"2010-12-07 00:00:00",
"FECHA_BAJA":null,
"5":null,
"CIF":null,
"6":null,
"TELEFONO_CASA":"",
"7":"",
"TELEFONO_MOVIL":"",
"8":"",
"EMAIL_TRABAJO":"",
"9":"",
"EMAIL_PARTICULAR":"",
"10":"",
"COLOR":"16777215",
"11":"16777215",
"ADMINISTRADOR":"0",
"12":"0",
"COD_PERSONA":"9",
"13":"9",
"IMPRESORA_ETIQUETAS":"",
"14":"",
"IMP_JUSTIFICANTES":"",
"15":"",
"VER_SESIONES":"0",
"16":"0",
"COD_EMPRESA":"0",
"17":"0",
"FECHA_TRABAJO":null,
"18":null,
"MEMORIZAR_FECHA":"0",
"19":"0",
"AVISOS_PAGOS":"0",
"20":"0",
"AVISOS_COBROS":"0",
"21":"0",
"AVISOS_DIAS":"0",
"22":"0",
"AVISOS_CONTRATOSC":"0",
"23":"0",
"24":"0"
}
]
And this is my code (extract):
let url = URL(string : "http://192.168.0.252:6996/datos/policlinica/webservices/valida.php")
let session = URLSession.shared
let request = NSMutableURLRequest(url: url!)
request.httpMethod = "POST"
let paramToSend = "usu=" + user + "&pass=" + pwd
request.httpBody = paramToSend.data(using: String.Encoding.utf8)
let task = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) in
guard let _:Data = data else{
return
}
do {
let json = try JSONSerialization.jsonObject(with: data!, options: [])
print (json) //I can see my json in console
let cod_persona = json["COD_USUARIO"]
print (cod_persona)
//error: Type 'Any' has no subscript members
} catch {
print ("error")
return
}
})
task.resume()
I have tried many examples of the internet, but I can not read a specific JSON data. For example, I would like to read the "COD_USUARIO" field and save the data in a variable, but I can not get it to work well for me.
Any advice on this theme or what am I doing wrong (sure many things)

I think your problem is that your json contains array objects, so I would call it like:
json[0]["COD_USUARIO"]
Because COD_USUARIO is in the first array of the json.

Related

Invalid top-level type in JSON write Swift 4

I am trying to learn JSON parsing. I have written an API in Laravel, which returns status : 200 in response. What I did is this:
guard let url = URL(string: "http://localhost/workon-api/public/api/register") else { return }
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
let newUser = User.init(name: "Rob", email: "abc#gmail.com", password: "12345678")
do {
let jsonBody = try JSONEncoder().encode(newUser)
request.httpBody = jsonBody
} catch { }
URLSession.shared.dataTask(with: request) { (data, response, error) in
guard let data = data else { return }
do {
let json = try JSONSerialization.data(withJSONObject: data, options: .prettyPrinted)
print(json)
} catch {}
}.resume()
Now, I am getting this error: Invalid top-level type in JSON write and app's crashing. After searching, I used this:
let json = try JSONSerialization.jsonObject(with: data, options: [])
And, it works. Why the previous method is not working? And, I get a response like this if I try to return the collected userInfo.
status = "{\"name\":\"Rob\",\"email\":\"abc#gmail.com\",\"password\":\"12345678\"}";
Why are back-slashes there? Are these okay? And, what is Gzip data? I know I am asking a lot, but I need to understand this. Thanks in advance.
P.S. : Here is the User Model.
struct User: Encodable {
let name : String?
let email : String?
let password : String?
}
First of all the backslashes are virtual. The framework adds them to be able to print double quotes within a literal string.
Secondly dataTask returns serialized JSON Data so to get a dictionary or array from the data you have to call jsonObject(with.
let object = try JSONSerialization.jsonObject(with: data)
print(object)

How to POST data from multiple view controllers to server with JSON using SWIFT

I need help with combining data collected from firstVC, secondVC, and thirdVC and serializing those in the fourthVC.
This link helps with one VC but I have to send only ONE FILE of JSON DATA to the server.
How to create and send the json data to server using swift language
The other method is passing a dictionary array from firstVC, secondVC, and thirdVC to the fourthVC and from the fourthVC convert the dictionaries into JSON. But i don't know how to do that.
I used the format from the answer provided in the link above, but if you need additional info, I will gladly cooperate. Thanks!
PS. Please give me useful comments that will help in any way. I need the code and not feedbacks like doing my own research and such cause I have been stressing about this for nearly a month now.
This is the UserDefault keys
if let AC = UserDefaults.standard.value(forKey: "Acc") as? String {
labeltext.text = "\(AC)"
}
if let TY = UserDefaults.standard.value(forKey: "Taxyear") as? String {
taxtext.text = "\(TY)"
}
if let BB = UserDefaults.standard.value(forKey: "Bsb") as? String {
bsbtext.text = "\(BB)"
}
Here is my JSON code
#IBAction func save(_ sender: Any){
typealias JSONDictionary = [String:Any]
let parameters = ["BankAccountNumber": "Acc", "Tax Year": "Taxyear", "my-bsb": "Bsb"]
let url = URL(string: "https://server:port/")! //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
let valid = JSONSerialization.isValidJSONObject(parameters) // true
print (valid)
do {
request.httpBody = try JSONSerialization.data(withJSONObject: parameters, options: .prettyPrinted) // pass dictionary to nsdata object and set it as request body
} catch let error {
print(error)
}
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()
let alertMessage = UIAlertController(title: "Saved!", message: "We have recorded your information", preferredStyle: UIAlertControllerStyle.alert)
let action = UIAlertAction(title:"Okay", style: UIAlertActionStyle.default, handler: nil)
alertMessage.addAction(action)
self.present(alertMessage, animated: true, completion: nil)
}
I solved it by first storing them in a variable
var TITLE = UserDefaults.standard.value(forKey: "Title")
var GN = UserDefaults.standard.value(forKey: "GivenNames")
var LN = UserDefaults.standard.value(forKey: "LastName")
Then I placed them in a parameter and that's done. It was so obvious that I can't believe I didn't solve it sooner
#IBAction func save(_ sender: Any){
let parameters = ["Tax Year": TaxYear, "Title": TITLE, "first-name": GN, "sur-name": LN]

Swift cannot convert json array to a NSArray

I am trying to get a json data from webpage and put it into my app. I have search so many things online and do not find any of them solve my problem.
The sample json is here
[{"id":"1","name":"Clean Archutecture","ISBN":"9780134494166","phone":null,"email":null,"comment":null,"last_update":"2018-03-10 22:53:29","price":"40","type":"sell"},{"id":"2","name":"Math Book","ISBN":null,"phone":null,"email":null,"comment":null,"last_update":"2018-03-10 22:53:54","price":null,"type":"want"},{"id":"3","name":"abc","ISBN":null,"phone":"hi","email":null,"comment":null,"last_update":"2018-03-11 19:58:00","price":"14.5","type":"want"},{"id":"4","name":"asd","ISBN":"1234","phone":"546","email":"dgf#asdc.com","comment":"234","last_update":"2018-03-11 19:59:57","price":"123","type":"want"}]
Swift code:
import Foundation
import UIKit
class Books: NSObject{
let urlRootPath = "http://maichongju.com/dbbs.php"
let method = "GET" //This is design for the php
func getData(type:String){
var result = NSArray()
let urlPath: String = urlRootPath+"?method=GET&size=ALL"
let url: URL = URL(string: urlPath)!
let request: NSMutableURLRequest = NSMutableURLRequest(url: url)
request.httpMethod = "GET"
let task = URLSession.shared.dataTask(with: request as URLRequest){
data,response, error in
if error != nil{
print("error:!! \(String(describing: error))")
return
}
do {
result = try JSONSerialization.jsonObject(with: data!, options:JSONSerialization.ReadingOptions.allowFragments) as! NSArray
print(result )
}catch {
print(error)
}
//print(result)
}
task.resume()
}
}
Error message is
Error Domain=NSCocoaErrorDomain Code=3840 "Invalid value around
character 0." UserInfo={NSDebugDescription=Invalid value around
character 0.}
I have double check my json data, i put it into online json view and it show perfectly fine. And I really dont know how to fix this problem
You don't need to force cast json response
do like this:
jsonResponse = try JSONSerialization.jsonObject(with: data!, options: .allowFragments)
Convert it like this as this is Array of Dictioanry objects
if let responseArray: [[String:Any]] = jsonResponse as? [[String:Any]] {
// DO HERE
}
I hope this will work for you
For safe side you https://github.com/Alamofire/Alamofire for Network request and for JSON : https://github.com/SwiftyJSON/SwiftyJSON
Update:
let urlPath: String = urlRootPath+"?method=GET&size=ALL"
i think is incorrect, In your body you have added POST but in URL you are appending method=GET
request.httpMethod = "POST"

Parsing nested Json data in swift 3

I am getting unexpected values back when i am parsing my json data from my api, i may be doing something wrong here as i'm quite new to swift but i was getting correct values before when i was receiving one "key" but now i have added two i cannot seem to parse the values properly.
This is the json collected from the address my code is receiving, (sorry if its hard to read havn't worked out how to do line breaks yet in my ruby api)(as long as its functional im not too worried at the moment)
{
"ratings":{
"elements":{"Ready Position":[{"description":"Neutral Grip","values":"1,2,3,4,5"},{"description":"Back Straight (Concave ir Convex?)","values":"1,2,3,4,5"},{"description":"Body Low \u0026 Feet a little more than sholder width apart","values":"1,2,3,4,5"},{"description":"Weight on Balls of Feet","values":"1,2,3,4,5"},{"description":"Head Up","values":"1,2,3,4,5"},{"description":"Sholder Blades Close","values":"1,2,3,4,5"},{"description":"Eyes Drilled","values":"1,2,3,4,5"}],"Split Step":[{"description":"Ready Position Conforms","values":"Yes,No"},{"description":"Body Position Low","values":"1,2,3,4,5"},{"description":"Legs Loaded/Prepared","values":"1,2,3,4,5"}]}
},
"comments":{}
}
Now, My swift code looks like this
let playerAPIurl = "http://linkcoachuat.herokuapp.com/api/v1/session/element?organisation=" + userorganisation + "&group=" + urlGroupSelected + "&sport=" + usersport
print(playerAPIurl)
var request = URLRequest(url: URL(string: playerAPIurl)!)
request.httpMethod = "GET"
let configuration = URLSessionConfiguration.default
let session = URLSession(configuration: configuration, delegate: nil, delegateQueue: OperationQueue.main)
let task = session.dataTask(with: request) { (data, response, error) in
if error != nil {
print("ERROR")
}
else{
do {
let json = try JSONSerialization.jsonObject(with: data!) as? [String: AnyObject]
print(json)
And this is the output im getting from this print(json)
Optional({
comments = {
};
ratings = {
};
})
I know i shouldnt be getting anything more in the comments part, but in the ratings part there should be some data?
so after recieving the json and dealing with parsing it i need to access this part of it ["ratings"]["elements"] and after that im all good
thanks in advance and please bare in mine im very new to swift
Thanks
Try the below code. The url used in below code has your JSON data. This code is printing the output correctly.
func testApi(){
let url = URL(string: "https://api.myjson.com/bins/jfccx")
let session = URLSession.shared
let request = URLRequest(url: url!)
//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 let data = data, error == nil else {
return
}
do {
//create json object from data
if let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] {
print(json)
}
} catch let error {
print(error.localizedDescription)
}
})
task.resume()
}

Trouble converting JSON to data with Swift

I am trying to learn Swift. One of my projects is to try to retrieve JSON data from an internal web service (a group of Python CGI scripts) and convert it into a Swift object. I can do this easily in Python, but I am having trouble doing this in Swift. Here is my playground code:
import UIKit
import XCPlayground
XCPlaygroundPage.currentPage.needsIndefiniteExecution = true
let endpoint: String = "http://pathToCgiScript/cgiScript.py"
let url = NSURL(string: endpoint)
let urlrequest = NSMutableURLRequest(URL: url!)
let headers: NSDictionary = ["User-Agent": "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)",
"Content-type": "application/x-www-form-urlencoded", "Accept": "text/plain"]
urlrequest.allHTTPHeaderFields = headers as? [String : String]
urlrequest.HTTPMethod = "POST"
let config = NSURLSessionConfiguration.defaultSessionConfiguration()
let session = NSURLSession(configuration: config)
let task = session.dataTaskWithRequest(urlrequest) {
(data, response, error) in
guard data != nil else {
print("Error: did not receive data")
return
}
guard error == nil else {
print("Error calling script!")
print(error)
return
}
do {
guard let received = try NSJSONSerialization.JSONObjectWithData(data!, options: []) as?
[String: AnyObject] else {
print("Could not get JSON from stream")
return
}
print(received)
} catch {
print("error parsing response from POST")
}
}
task.resume()
I know making a 'POST' to retrieve data may look odd, but that is how the system is set up. I keep on getting:
Could not get data from JSON
I checked the response, and the status is 200. I then checked the data's description with:
print(data?.description)
I got an unexpected result. Here is a snippet:
Optional("<0d0a5b7b 22535441 54555322 3a202244 6f6e6522 2c202242 55535922...
I used Mirror, and apparently the type is NSData. Not sure what to make of this. I have tried to encode the data with base64EncodedDataWithOptions. I have tried different NSJSONReadingOptions as well to no avail. Any ideas?
Update:
I used Wireshark to double check the code in the Playground. Not only was the call made correctly, but the data being sent back is correct as well. In fact, Wireshark sees the data as JSON. The issue is trying to turn the JSON data into a Swift object.
I figured out what was wrong. I was casting to the wrong type. This is the new code:
guard let received = try! NSJSONSerialization.JSONObjectWithData(data!, options:.AllowFragments) as? [AnyObject]
The JSON was not returning an array of dictionaries but an array of objects.