Below is my json file
and the url is http://localhost/country.php
I want this data into uitable view swift
{ name: ["India","USA","China"] }
let url = NSURL(string: "http://localhost/country.php")
let userdata = NSData(contentsOf: url! as URL)
do {
let values = try JSONSerialization.jsonObject(with: userdata as! Data, options: .allowFragments) as! NSDictionary
print(values)
print("Parse success")
} catch let error as NSError
{
print(error)
return
}
this is the code
please help
So. First of all: Your JSON is not a valid JSON and your URL is (of course) not working. My guess is your JSON looks like that:
{
"name": ["India",
"USA",
"China"
]
}
If so you can change your code like that and it is working as expected:
let jsonString = """
{
"name": ["India",
"USA",
"China"
]
}
"""
let userData = jsonString.data(using: .utf8)!
do {
let values = try JSONSerialization.jsonObject(with: userData) as! [String: Any]
print(values)
print("Parse success")
} catch let error as NSError
{
print(error)
}
Like one comment already mentioned: Try to avoid NStypes in Swift if it is not really needed.
Hope it helps.
And in addition: It is generally a bad practice to load a response from server sync. You should use URLSession and do it async. But this is another thing...
So the full example for your use case would look like this:
let url = URL(string: "http://localhost/country.php")!
let userData = try! Data(contentsOf: url)
do {
let values = try JSONSerialization.jsonObject(with: userData) as! [String: Any]
print(values)
print("Parse success")
} catch let error as NSError
{
print(error)
}
I force unwrap in the example above. I do not recommend that. Savely unwrap your optionals is the better way.
Related
I try to load the user profile like below
#IBAction func Btn_LoadDataFromDataBase(_ sender: UIButton) {
let myurl = "site.com/profile.php"
LoadURL(url: myurl)
}
func LoadURL(url: String) {
do{
let appURL = URL(string: url)! // convert string to URL
let data = try Data(contentsOf: appURL)
//error here on this line below :
let json1 = try JSONSerialization.jsonObject(with: data ) as! [String: Any]
print(json1)
let query1 = json1["profile"] as! [String: Any]
print(query1)
label_email.text = "Email : (query1["email"]!)"
}catch{
print("error in url")
}
}
if I test the json via webbrowser I get it like this:
{profile : [{"0":"999","id":"999","1":"1","email":"blabla#gmail.com","2":"1111","tel":"00122222222","3":"0" ..........
php code:
print "{profile : ".json_encode($user_profile,JSON_UNESCAPED_UNICODE)."}";
mysql_close($db);
?>
Please read the JSON carefully, there are only two different collection types
{} is dictionary ([String: Any])
[] is array ([Any] but in most cases [[String: Any]])
so the result for query1 (I changed the variable names to something more descriptive) is an array and you need a loop to print all elements:
let profileData = try JSONSerialization.jsonObject(with: data ) as! [String: Any]
let profiles = profileData["profile"] as! [[String: Any]] // could be even [[String:String]]
for profile in profiles {
print("Email :", profile["email"]!")
}
I'm wondering why so many owners of web services send the PHP arrays unnecessarily with both index and key.
And never load data from a remote URL synchronously, use asynchronous URLSession
You're better using URLRequest for async requests. You will need to pass your appURL as a parameter in a URLRequest and handle the answer in its completion handler.
An example:
let urlString = "https://swift.mrgott.pro/blog.json"
guard let url = URL(string: urlString) else { return }
URLSession.shared.dataTask(with: url) { (data, response, error) in
if error != nil {
print(error!.localizedDescription)
}
guard let data = data else { return }
// Implement JSON decoding and parsing
do {
let articlesData = try JSONDecoder().decode([OBJECT YOU WANT].self, from: data)
} catch let jsonError {
print(jsonError)
}
}.resume()
I'm trying to parse this JSON in Swift 3, but it crashes.
Here's the code
do{
let data1: Data = try! Data(contentsOf: NSURL(string: "https://gist.githubusercontent.com/DesWurstes/00baf946bd6d27e7e9355bd6e9969230/raw/a0de898faea8ddedb11b0db516967d0666255633/gist.json") as! URL)
let jsono = try JSONSerialization.jsonObject(with: data1, options: []) as! [String: Any]
}catch{
// catch isn't used here.
}
Here's the error I get when it crashes:
Could not cast value of type '__NSArrayI' (0x7fffe9cb9c08) to 'NSDictionary' (0x7fffe9cba158).
It crashes because not all of the elements of the array are string. (The root of the JSON is an array.)
To prevent it from crashing, changing the third line with this will be suitable:
let jsono = try JSONSerialization.jsonObject(with: data1, options: [])
But then, its type will be Any and I won't be able to parse it with
let string = jsono["something"] as! [String: Any] // Type "Any" has no subscript members
and this code won't run:
if let array = jsono as? [String: Any] {
print("test") // Doesn't print
}
While trying to fix error in the first code, I thought this code may work (Because it says can't convert Array to Dictionary):
let jsono = try JSONSerialization.jsonObject(with: data1, options: []) as! [String]
but it results...
Could not cast value of type '__NSDictionaryI' (0x7fffe9cba108) to 'NSString' (0x7fffea072f38).
Then how can I parse this JSON?
It looks like the JSON response returned from server is an array containing dictionaries of type [String: Any] so you can do:
if let array = jsono as? [[String: Any]] {
print("test") // Will print
for dictionary in array {
print(dictionary["url"] as! String)
}
}
Here you can download the playground I've written to test it out.
you have parse array response so you need to type cast json as? [[String: Any]]..
if your response is dictonary then you need to parse like json as? [String: Any]
func Callservice()
{
let jsonUrlString = "url"
guard let url = URL(string: jsonUrlString) else { return }
URLSession.shared.dataTask(with: url) { (data, response, err) in
guard let data = data else { return }
do {
let courses = try JSONDecoder().decode([Course].self, from: data)
self.arrayData = courses
print(courses)
} catch let jsonErr {
print("Error serializing json:", jsonErr)
}
}.resume()
}
struct course:decodable{
let name:string?
}
This is making post requests, but it is treating the json as a string, which shows up on the server as (stuff): ''. I don't know how to fix it. (When I used python to implement this, it was perfect.)
let json: [String: Any] = ["id": 1, "checksum": "hey"]
let jsonData = try? JSONSerialization.data(withJSONObject: json)
/*print(jsonData!)
let parsedData = try? JSONSerialization.jsonObject(with: jsonData!, options: [])
print(parsedData!)*/
//print(parsedData)
// create post request
let url = URL(string: "http://10.240.81.23:3000/updateProfile")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
// insert json data to the request
request.httpBody = jsonData
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else {
print(error?.localizedDescription ?? "No data")
return
}
let responseJSON = try? JSONSerialization.jsonObject(with: data, options: [])
if let responseJSON = responseJSON as? [String: Any] {
print(responseJSON)
}
}
task.resume()
Consider using Alamofire for networking, it is amazingly easy to use and works great. Also SwiftyJSON that makes JSON parsing and manipulation really easy and optional-safe.
You can use Carthage to install those two frameworks easily.
I have a JSON file called points.json, and a read function like:
private func readJson() {
let file = Bundle.main.path(forResource: "points", ofType: "json")
let data = try? Data(contentsOf: URL(fileURLWithPath: file!))
let jsonData = try? JSONSerialization.jsonObject(with: data!, options: []) as! [String:Any]
print(jsonData)
}
It does not work, any help?
Your problem here is that you force unwrap the values and in case of an error you can't know where it comes from.
Instead, you should handle errors and safely unwrap your optionals.
And as #vadian rightly notes in his comment, you should use Bundle.main.url.
private func readJson() {
do {
if let file = Bundle.main.url(forResource: "points", withExtension: "json") {
let data = try Data(contentsOf: file)
let json = try JSONSerialization.jsonObject(with: data, options: [])
if let object = json as? [String: Any] {
// json is a dictionary
print(object)
} else if let object = json as? [Any] {
// json is an array
print(object)
} else {
print("JSON is invalid")
}
} else {
print("no file")
}
} catch {
print(error.localizedDescription)
}
}
When coding in Swift, usually, ! is a code smell. Of course there's exceptions (IBOutlets and others) but try to not use force unwrapping with ! yourself and always unwrap safely instead.
The Swift 5 / iOS 12.3 code below shows a possible rewrite of your method that avoids force unwrap on optional values and handles gently potential errors:
import Foundation
func readJson() {
// Get url for file
guard let fileUrl = Bundle.main.url(forResource: "Data", withExtension: "json") else {
print("File could not be located at the given url")
return
}
do {
// Get data from file
let data = try Data(contentsOf: fileUrl)
// Decode data to a Dictionary<String, Any> object
guard let dictionary = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] else {
print("Could not cast JSON content as a Dictionary<String, Any>")
return
}
// Print result
print(dictionary)
} catch {
// Print error if something went wrong
print("Error: \(error)")
}
}
Is it possible that someone could show me how to get the names of these pizza places printing out? My application prints out the expected "Status Code: 200". However, my console only shows empty brackets []. I suspect that I am not pulling values from my JSON object properly.
I'm using this link for my API.
Link For API
Question
How can I properly fetch values from my serialized JSON object?
relevant code:
// Response
if let httpResponse = response as? NSHTTPURLResponse where httpResponse.statusCode == 200, let data = data {
print("Status Code: \(httpResponse.statusCode)")
do {
let json = try NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers)
if let pizzaPlaces = json["response"] as? [[String: AnyObject]] {
for place in pizzaPlaces {
if let name = place ["name"] as? String {
self.PizzaClass.append(name)
}
}
}
} catch {
print("Error Serializing JSON Data: \(error)")
}
print(self.PizzaClass)
}
}).resume()
You need to cast your NSJSONSerialization.JSONObjectWithData result as a [String:AnyObject].
let jsonObject = try NSJSONSerialization.JSONObjectWithData(returnedData, options: .MutableLeaves) as! [String: AnyObject]
Once you have that all you need to do is pay attention to what you're casting. Take the code below for an example. If we want to get our response object using jsonObject["response"] what kind of data structure do we have?
"response": {
"venues": [{
//... continues
}]
}
On the left we have "response" which is a string, on the right we have {} which is an AnyObject. So we have [String: AnyObject]. You just need to think about what object your dealing with piece by piece. Below is a working example that you can just paste into your application.
full working code:
func getJson() {
let request = NSMutableURLRequest(URL: NSURL(string: "https://api.foursquare.com/v2/venues/search?client_id=0F5M0EYOOFYLBXUOKTFKL5JBRZQHAQF4HEM1AG5FDX5ABRME&client_secret=FCEG5DWOASDDYII4U3AAO4DQL2O3TCN3NRZBKK01GFMVB21G&v=20130815%20&ll=29.5961,-104.2243&query=burritos")!)
let session = NSURLSession.sharedSession()
request.HTTPMethod = "GET"
request.addValue("application/json", forHTTPHeaderField: "Accept")
let task = session.dataTaskWithRequest(request) { (data: NSData?, response: NSURLResponse?, error: NSError?) -> Void in
guard let testResponse = response as? NSHTTPURLResponse else {
print("\(response)")
return
}
guard let status = HTTPStatusCodes(rawValue: testResponse.statusCode) else {
print("failed to unwrap status")
return
}
print(status)
switch status {
case .Created:
print("ehem")
case .BadRequest:
print("bad request")
case .Ok:
print("ok")
guard let returnedData = data else {
print("no data was returned")
break
}
do {
let jsonObject = try NSJSONSerialization.JSONObjectWithData(returnedData, options: .MutableLeaves) as! [String: AnyObject]
guard let response = jsonObject["response"] as? [String: AnyObject] else { return }
guard let venues = response["venues"] as? [AnyObject] else { return }
guard let location = venues[0]["location"] as? [String:AnyObject] else { return }
guard let formattedAddress = location["formattedAddress"] else { return }
print("response: \n\n \(response)\n------")
print("venues : \n\n \(venues)\n-------")
print("location : \n\n \(location)\n------")
print("formatted address : \n \(formattedAddress)")
} catch let error {
print(error)
}
// update user interface
dispatch_sync(dispatch_get_main_queue()) {
print("update your interface on the main thread")
}
}
}
task.resume()
}
place this either in its own file our outside of the class declaration,
enum HTTPStatusCodes : Int {
case Created = 202
case Ok = 200
case BadRequest = 404
}
Not that this was what you are looking for, but since you are new to Swift take a look at Alamofire. It handles JSON serialization for you. And when you need to chain calls PromiseKit is super slick.
Alamofire.request(.GET, url).responseJSON {response in
switch (response.result) {
case .Success(let value):
let pizzas = JSON(value).arrayValue
for place in pizzaPlaces {
if let name = place ["name"] as? String {
self.PizzaClass.append(name)
}
}
case .Failure(let error):
if let data = response.data, let dataString = String(data: data, encoding: NSUTF8StringEncoding) {
print("ERROR data: \(dataString)")
}
print("ERROR: \(error)")
}
}