Parsing JSON object to NSArray in Swift 3 - ios

After i convert my project to swift 3 i had run time error when i try to parsing JSON object to NSArray this my code
let receipt: Data! = try? Data(contentsOf: receiptURL)
if receipt == nil {//NSData(contentsOfURL: receiptURL, options: nil, error: nil)!
// validateReceipt(false)
return
}
let base64Data: String = receipt.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0)) as String
let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).last?.path//
do{
let payload: Dictionary = ["receipt-data" : base64Data as String, "password": sharedSecret as String ]
let receiptData = try JSONSerialization.data(withJSONObject: payload, options: JSONSerialization.WritingOptions.prettyPrinted)
let request = NSMutableURLRequest(url: URL(string: serverURL)!, cachePolicy: NSURLRequest.CachePolicy.useProtocolCachePolicy, timeoutInterval: 10) // ur website
request.httpMethod = "POST"
request.httpBody = receiptData as! Data?
var response: URLResponse?
let resultData = try NSURLConnection.sendSynchronousRequest(request as URLRequest, returning: &response)
do{
let json = try JSONSerialization.jsonObject(with: resultData, options: .mutableLeaves) as? NSDictionary
let statusCode = (json?.object(forKey: "status") as! NSNumber).intValue
switch(statusCode){
case 21000, 21002, 21003, 21004, 21006:
return
// break
case 21005:
//Server is not available: Save recipt data and try again later
return
case 21007:
validateReceipt(true)
return
case 21008:
validateReceipt(false)
return
default:
break
}
//print("**********************************")
//print("json :: ", json )
//print("**********************************")
if let parseJSON = json {
let latest_receipt_info:NSArray = (parseJSON.object(forKey: "receipt") as AnyObject).object(forKey: "in_app") as! NSArray
//var ms = 0
//parse the json reponse and add the objects into array
for i in 0 ..< latest_receipt_info.count {
let object:[String: String] = latest_receipt_info.object(at: i) as! [String : String]
let strMS = object["expires_date_ms"]
let prodId = object["product_id"]
if(prodId == iAPItems["LifeTime"] || prodId == iAPItems["Remove_Ads"]){
latestObjectsForEachProduct[prodId!] = object
}else{
if let oldTransaction = latestObjectsForEachProduct[prodId!] {
let strOldMS = oldTransaction["expires_date_ms"]
print("oldTransaction :: ",prodId, " :: ",strOldMS)
if( strMS!.toDouble() > strOldMS!.toDouble() ){
//latestObject = object
latestObjectsForEachProduct[prodId!] = object
//ms = str!.toInt()
}
}else{
latestObjectsForEachProduct[prodId!] = object
}
}
}
the errors appears on this line
let latest_receipt_info:NSArray = (parseJSON.object(forKey: "receipt") as AnyObject).object(forKey: "in_app") as! NSArray
i dont know what should i do , if any one can help
Note that on swift 2 its work

Try this code
let json = try JSONSerialization.jsonObject(with: resultData, options: .mutableLeaves) as? NSDictionary
let statusCode = (json?.object(forKey: "status") as! NSNumber).intValue
to replace this code
let json = try JSONSerialization.jsonObject(with: resultData, options: .mutableLeaves) as? [String:AnyObject]
let statusCode = (json?["status"] as! NSNumber).intValue
let latest_receipt_info:NSArray = (parseJSON.object(forKey: "receipt") as AnyObject).object(forKey: "in_app") as! NSArray
To replace this code
let latest_receipt_info:NSArray = parseJSON["receipt"]!["in_app"] as! NSArray

Related

Api is not showing serialized json output

I have created simple login screen attached with loginViewController.swift. Here are the urls
let login_url = "http://192.168.100.11:9000//users/authenticate"
let checksession_url = "http://192.168.100.11:9000//users/authenticate"
I have simple login api. The web service it is showing response on post man web service but it is not displaying serialized json output on Xcode. How to get serialize json from url?
The api is getting two parameters from username="andrews" and password="admin2"
func login_now(username:String, password:String){
let post_data: NSDictionary = NSMutableDictionary()
post_data.setValue(username, forKey: "username")
post_data.setValue(password, forKey: "password")
let url:URL = URL(string: login_url)!
let session = URLSession.shared
let request = NSMutableURLRequest(url: url)
request.httpMethod = "POST"
request.cachePolicy = NSURLRequest.CachePolicy.reloadIgnoringCacheData
var paramString = ""
for (key, value) in post_data {
paramString = paramString + (key as! String) + "=" + (value as! String) + "&"
}
let endIndex = paramString.index(paramString.endIndex, offsetBy: -1)
let truncated = paramString.substring(to: endIndex)
paramString=truncated
print(paramString) // This won't consist of last &
request.httpBody = paramString.data(using: String.Encoding.utf8)
let task = session.dataTask(with: request as URLRequest, completionHandler: {
(
data, response, error) in
guard let _:Data = data, let _:URLResponse = response , error == nil else {
return
}
let json: Any?
do
{
json = try JSONSerialization.jsonObject(with: data!, options: [])
//////////////here json object is not formed to get json output
print("abc")
print(json)
}
catch
{
return
}
guard let server_response = json as? NSDictionary else
{
return
}
if let data_block = server_response["data"] as? NSDictionary
{
if let session_data = data_block["session"] as? String
{
self.login_session = session_data
let preferences = UserDefaults.standard
preferences.set(session_data, forKey: "session")
DispatchQueue.main.async(execute: self.LoginDone)
}
}
})
task.resume()
}
Here json object is not formed to get serialized json output.how to get the serialized json out put on Nslog? You can download the project from this link.

Working with JSON data retrieving into Swift data types

I'm trying to get data from a URL. It was successful. I can download and convert to a dictionary[String : Any] but response is in nested loops. I don't to how to retrieve. Can someone suggest how to get text and value in the response?
func getDataFromUrl() {
let url = URL(string: "https://maps.googleapis.com/maps/api/distancematrix/json?units=imperial&departure_time=1408046331&origins=37.407585,-122.145287&destinations=37.482890,-122.150235")
let request = NSMutableURLRequest(url: url!)
let session = URLSession.shared
request.httpMethod = "GET"
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: {(data, response, error) in
do {
let jsonData = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers) as? [String: Any]
let destinationAddress = jsonData!["destination_addresses"]
print("Destination address \(String(describing: destinationAddress!))")
let origin_addresses = jsonData!["origin_addresses"]
print("Origin_addresses \(String(describing: origin_addresses!))")
let rows = jsonData!["rows"]
print("Rows \(String(describing: rows!))")
// Here I want to print text and value.
} catch {
// handle error
}
})
dataTask.resume()
}
The above answers work, but in my opinion the more swiftier approach is to use Codable.
class MyResponseType:Codable {
let destination_addresses:String
let rows:[MyCustomRowData]
}
class MyCustomRowData:Codable {
let elements:[MyCustomElementsData]
}
class MyCustomElementsData:Codable {
// properties here
}
Doing this, parsing the json is done like this:
let response = try? JSONDecoder().decode(MyResponseType.self, from: data)
Where the data variable is just the retrieved Data object from the request.
Initially you have to set up some boilerplate code to replicate your expected data format, but working with it is really worth it (and it makes it highly testable).
When the decode succeeds you have a perfectly typed object, it can also have optionals. It just wont decode if fields are missing or of the wrong type (which is a good thing).
Here is the way you can parse text and Value from response:
do{
if let jsonData = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers) as? [String: Any] {
if let destinationAddress = jsonData["destination_addresses"] as? [String] {
print(destinationAddress) //["1 Hacker Way, Menlo Park, CA 94025, USA"]
}
if let origin_addresses = jsonData["origin_addresses"] as? [String] {
print(origin_addresses) //["3251 Hillview Ave, Palo Alto, CA 94304, USA"]
}
if let rows = jsonData["rows"] as? [[String: AnyObject]] {
if rows.indices.contains(0) {
if let elements = rows[0]["elements"] as? [[String: AnyObject]] {
for element in elements {
if let duration = element["duration"] as? [String: AnyObject] {
let text = duration["text"] as? String ?? ""
print(text) //17 mins
let value = duration["value"] as? Int ?? 0
print(value) //1010
}
if let distance = element["distance"] as? [String: AnyObject] {
let text = distance["text"] as? String ?? ""
print(text) //7.2 mi
let value = distance["value"] as? Int ?? 0
print(value) //11555
}
}
}
}
}
}
}catch{ //error handle
}
Use this code:
let rows = jsonData["rows"] as! Array
let element = rows[0] as! Dictionary
let elementArray = element.value(forKey: "elements")
let distance = elementArray[0].value(forKey: "distance")
let text = distance.value(forKey: "text")
print(text)
let value = distance.value(forKey: "value")
print(value)

Deserialize JSON in swift

Is there a way to properly deserialize an json in swift that is this structure?
{
Usuario = (
{
"picture_url" = "";
id = 229;
name = "ABC";
}
);}
I tested this with jsonHelper library
let jsonData = try NSJSONSerialization.JSONObjectWithData(data!, options:NSJSONReadingOptions.MutableContainers )
let jsonString = jsonData
var mstemp = [usuario]()
mstemp <-- jsonString
but only worked for jsons this structure
{"name": "myUser", "id": "1","picture_url": ""}
Update
code:
let urlFinal = URLSERVIDOR+"/ws/rest/Geral/consultaUsuario?token=\(validotoken)&email=\(validoEmail)&senha=\(SenhaCriptada)"
let jsonUrl = urlFinal
let session = NSURLSession.sharedSession()
let shotsUrl = NSURL(string: jsonUrl)
let task = session.dataTaskWithURL(shotsUrl!) {data, response, error in
guard data != nil else {
falha()
return
}
do {
let jsonData = try NSJSONSerialization.JSONObjectWithData(data!, options:NSJSONReadingOptions.MutableContainers )
let jsonString = jsonData
var mstemp = [usuario]()
mstemp <-- jsonString
dispatch_async(dispatch_get_main_queue(),{
sucesso(usuarioBaixado: mstemp)
});
} catch _ {
falha()
}
}
task.resume()
Try this:
URLSession.shared.dataTask(with: shotsUrl!) {
(data, response, error) in
guard data != nil else {
return
}
guard let json = try? JSONSerialization.jsonObject(with: data!, options: []) as! [String: AnyObject],
let usuario = json["Usuario"] as! AnyObject else {
return
}
print ("Usuario:\n\t\(usuario["id"] as! Int)")
print ("\t\(usuario["name"] as! String)")
print ("\t\(usuario["picture_url"] as! String)")
}

JSON Parsing & Optionals in Swift 3

So i recently updated to Swift 3/XCode 8 and some of my code went hay-wire. I've read that some syntax changes have been made but I can't seem get this one right.
I make a request to Twitter and get JSON back:
func forLoadStats(completion: (AnyObject?, NSError?) -> Void)
{
var clientError: NSError?
let idString = api.getUserID()
let client = TWTRAPIClient()
let request = client.urlRequest(withMethod: "GET", url: "https://api.twitter.com/1.1/users/show.json", parameters: ["user_id" : 27446437], error: &clientError)
client.sendTwitterRequest(request)
{ (response, data, connectionError) in
if (connectionError == nil)
{
do {
if let json: Any = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [AnyObject]
{
if let json = json, let immage = json?["profile_image_url_https"] as? String
{
//Make ProfilePic edges round
self.profPic.layer.cornerRadius = 42
self.profPic.clipsToBounds = true
//let immage = image["profile_image_url_https"] as String
let _vImageUrl = immage.replacingOccurrences(of: "_normal", with: "")
let urlProfilePic = NSURL(string: _vImageUrl)
let urlPP = NSData(contentsOf: urlProfilePic! as URL)
self.profPic.image = UIImage(data: urlPP! as Data)
let ScrName = json["screen_name"] as! String
self.scrNameLabel.text = "#\(ScrName)"
//Populate Followers Label.text
let flwrVar = json["followers_count"] as! Int
self.followerLbl.text = "\(flwrVar)"
//Populate Following Label.text
let flwngVar = json["friends_count"] as! Int
self.followingLbl.text = "\(flwngVar)"
//Populate Bio
let bio = json["description"] as! String
self.bioLabel.text = "\(bio)"
//created at date
let accountAge = json["created_at"] as! String
self.createdLbl.text = "\(accountAge)"
let tweetCount = json["statuses_count"] as! Int
self.tweetCount.text = "\(tweetCount)"
let likes = json["favourites_count"] as! Int
self.likesCount.text = "\(likes)"
let lists = json["listed_count"] as! Int
self.listedCount.text = "\(lists)"
}
}
}
catch let error
{
print(error)
}
}
}
}
I get an error on the second "If let" statement that says: "initializer for conditional binding must have optional type not 'Any.
Can someone explain why this is?
Your JSON is obviously a dictionary, a JSON dictionary in Swift 3 is [String:Any]
You caused the error by the silly Any annotation (which is supposed to be Any? but is practically nonsensical) because it confuses the compiler.
If you use a do block, try without question mark but use optional binding:
...
if let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String:Any] {
if let immage = json["profile_image_url_https"] as? String { ...
There are a couple of problems with the syntax. [AnyObject] will not work to use reference items such as json["profile_image_url_https"]. also, you are redeclaring json through let json = json, which makes it a non option in your let immage = json?["profile_image_url_https"] call, so that becomes a problem. This structure does not have any compiler errors
if let json = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String:Any]
{
if let json = json, let immage = json["profile_image_url_https"] as? String
{
}
}
This does not have any compiler errors.

Can't execute NSURLSession.sharedSession().dataTaskWithURL in Swift

I have a code to get an employee data from php returned Json which is the following :
[{"id":"1","email":"KK","password":"KKK","firstName":"KKK","lastName":"KK","photo":null,"phone":"22","mobile":"2","position":"SS","adminstrator_id":"1","department_id":"1"}]
Code I have try:
func getEmpById (id:String) {
emp = employee()
let myUrl = NSURL(string:"http://localhost/On%20Call%20App/scripts/getEmployee.php?id=\(id)")
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithURL(myUrl!, completionHandler: {
(data, response, error) -> Void in
do {
let json = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableContainers) as! [[String: AnyObject]]
let dic = json[0]
if let id = dic["id"] , firstName = dic["firstName"] ,lastName = dic["lastName"], mobile = dic["mobile"],phone = dic["phone"],email=dic["email"],pos=dic["position"]{
self.emp.setId(id as! String )
self.emp.setFirstName(firstName as! String)
self.emp.setLastName(lastName as! String)
self.emp.setPhone(phone as! String)
self.emp.setMobile(mobile as! String)
self.emp.setEmail(email as! String)
self.emp.setPosition(pos as! String)
}
} catch {
print(error)
}
})
task.resume()
}
The problem in this line let task = session.dataTaskWithURL(myUrl!, completionHandler:{ when the app reach this line it will directly go to task.resume() without printing any error
Any help to make this work ?
Your response is of Array type not Dictionary
let json = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableContainers) as! NSArray
let dic = json[0] as! NSDictionary
print(dic.objectForKey("email"))
It is batter if use use Swift array like this.
let json = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableContainers) as! [[String: AnyObject]]
let dic = json[0]
print(dic["email"])

Resources