My get data response is like
I want "title" and "date" should be shown in my view controller "label values"
get method calls when app running and the data should display in either text fields "or" in label
My Code is
guard let url = URL(string: "https://jsonplaceholder.typicode.com/users") else { fatalError() }
let session = URLSession.shared
session.dataTask(with: url) { (data, response, error) in
if let response = response {
print(response)
}
if let data = data {
print(data)
do {
let json = try JSONSerialization.jsonObject(with: data, options: [])
print(json)
} catch {
print(error)
}
}
}.resume()
out put is :
[
{
"id": 1,
"name": "Leanne Graham",
"username": "Bret",
"email": "Sincere#april.biz",
"address": {
"street": "Kulas Light",
"suite": "Apt. 556",
"city": "Gwenborough",
"zipcode": "92998-3874",
"geo": {
"lat": "-37.3159",
"lng": "81.1496"
}
},
"phone": "1-770-736-8031 x56442",
"website": "hildegard.org",
"company": {
"name": "Romaguera-Crona",
"catchPhrase": "Multi-layered client-server neural-net",
"bs": "harness real-time e-markets"
}
},
{
"id": 2,
"name": "Ervin Howell",
"username": "Antonette",
"email": "Shanna#melissa.tv",
"address": {
"street": "Victor Plains",
"suite": "Suite 879",
"city": "Wisokyburgh",
"zipcode": "90566-7771",
"geo": {
"lat": "-43.9509",
"lng": "-34.4618"
}
},
]
I want to print "username":
"email":
values in my Storyboard labels
The result contains multiple users, so you should first iterate over them and find the user you want. Then you can set text on your UI elements in the Main thread.
guard let url = URL(string: "https://jsonplaceholder.typicode.com/users") else { fatalError() }
typealias User = [String: Any]
let session = URLSession.shared
session.dataTask(with: url) { (data, response, error) in
if let response = response {
print(response)
}
if let data = data {
print(data)
do {
let usersJson = try JSONSerialization.jsonObject(with: data, options: []) as! [User]
print(usersJson)
// Since the result is an array of users
for user in usersJson {
guard let userName = user["username"] as? String else { return assertionFailure("Invalid username") }
print(userName)
// All UI works should done in main thread
DispatchQueue.main.async {
<#usernameLabel#>.text = username
}
}
} catch {
print(error)
}
}
}.resume()
I suggest you take a look at Swift Codable. It will boost your coding and minimize syntax and human errors.
Related
I am trying to create dynamic sectionIndexTitles for my tableView. I want to get all of the character names and then get the first letter of the name to create sectionIndexTitles, but I am having difficulty doing so.
I get the JSON from URL:
func downloadJSON(completed: #escaping () -> ()) {
let url = URL(string: "mytestURL")
let configuration = URLSessionConfiguration.ephemeral
let session = URLSession(configuration: configuration)
session.dataTask(with: url!) { (data, response, error) in
if error == nil {
do {
characters = try JSONDecoder().decode([CharacterStats].self, from: data!)
DispatchQueue.main.async {
completed()
}
} catch {
print("JSON Error")
}
}
}.resume()
}
The JSON looks like this:
[
{
"name": "Batman",
"type": "DC",
"gender": "male",
},
{
"name": "Captain America",
"type": "Marvel",
"gender": "male",
},
{
"name": "Captain Marvel",
"type": "Marvel",
"gender": "female",
}
]
And my struct looks like this:
public struct CharacterStats: Decodable {
let name: String
let type: String?
let gender: String?
}
I have posted a sample code for this here https://github.com/achuaswani/ListItemExample.git
I want to create extension for Dictionary [String:Any] which is received from API Response.
Right Now I am doing below way
I have created func getDataFromJson this is working fine, Please let me know how to do that.
func getDataFromJson(json: AnyObject) -> Data?{
do {
print("json = \(json)")
return try JSONSerialization.data(withJSONObject: json, options: JSONSerialization.WritingOptions.prettyPrinted)
} catch let myJSONError {
print("\n\n\nError => getDataFromJson => \(myJSONError)")
}
return nil;
}
This is my response and I want to "data" to Data
{
"status": true,
"message": "Country List",
"data": [
{
"id": 1,
"name": “ABC”,
"code": "A",
"phone_code": "+91”,
"flag": "country-flags/-shiny.png"
},
{
"id": 2,
"name": “ZYX”,
"code": “Z”,
"phone_code": "+1”,
"flag": "country-flags/-shiny.png"
}
]
}
I want to get data this way jsonResponse["data"].retriveData()
Here is a simple function that encodes the dictionary, the function throws any error so it can be properly handled. Since JSONSerialization.data(withJSONObject: takes an Any parameter this function can also be implemented for an array etc
extension Dictionary {
func retriveData() throws -> Data {
return try JSONSerialization.data(withJSONObject: self)
}
}
Simple example
let dict = ["abc": 123, "def": 456]
do {
let data = try dict.retriveData()
let result = try JSONDecoder().decode([String:Int].self, from:data)
print(result)
} catch {
print(error)
}
Another way is to use Result if you're on Swift 5 (shortened after comment from vadian)
extension Dictionary {
func retriveData() -> Result<Data, Error> {
return Result { try JSONSerialization.data(withJSONObject: self) }
}
}
and an example
let result = try dict.retriveData()
switch result {
case .success(let data):
let dictionary = try JSONDecoder().decode([String:Int].self, from:data)
print(dictionary)
case .failure(let error):
print(error)
}
a copy of your function transposed to an extension can be
extension Dictionary {
func retriveData() -> Data? {
do {
return try JSONSerialization.data(withJSONObject: self, options: .prettyPrinted)
} catch let myJSONError {
print("\n\n\nError => getDataFromJson => \(myJSONError)")
}
return nil
}
}
Correct json
{
"status": true,
"message": "Country List",
"data": [
{
"id": 1,
"name": "ABC",
"code": "A",
"phone_code": "+91",
"flag": "country-flags/-shiny.png"
},
{
"id": 2,
"name": "ZYX",
"code": "Z",
"phone_code": "+1",
"flag": "country-flags/-shiny.png"
}
]
}
Model
struct Datum: Codable {
let id: Int
let name, code, phoneCode, flag: String
}
Decoding data only
let str = """
{
"status": true,
"message": "Country List",
"data": [{
"id": 1,
"name": "ABC",
"code": "A",
"phone_code": "+91",
"flag": "country-flags/-shiny.png"
},
{
"id": 2,
"name": "ZYX",
"code": "Z",
"phone_code": "+1",
"flag": "country-flags/-shiny.png"
}
]
}
"""
do {
let dic = try JSONSerialization.jsonObject(with: Data(str.utf8)) as! [String:Any]
let content = try JSONSerialization.data(withJSONObject: dic["data"])
let dec = JSONDecoder()
dec.keyDecodingStrategy = .convertFromSnakeCase
let res = try dec.decode([Datum].self, from: content)
print(res)
}
catch {
print(error)
}
Please try this
// Response Dictionary
let jsonResponse : [String:Any] = ["data":["key1":"value1",
"key2":"value2",
"key3":"value3",
"key4":"value4"]]
// check dictionary contains value for key "data"
if let dataDict = jsonResponse["data"] as? [String:Any] {
// convert dictionary to data
let jsonData = dataDict.retriveData()
print("Json Data :- ", jsonData != nil ? "Success" : "Data is nil")
}
// Dictionary exxtension for converting dictionary to json data
extension Dictionary {
func retriveData() -> Data? {
do {
print("json = \(self)")
return try JSONSerialization.data(withJSONObject: self, options: JSONSerialization.WritingOptions.prettyPrinted)
} catch let myJSONError {
print("\n\n\nError => getDataFromJson => \(myJSONError)")
}
return nil;
}
}
I am working on a weather app that parses JSON data and sets the text of my label to the temp value of the JSON request. I got the value of id from the weather object array, but the temp is not in an array it is just an object. Can someone please tell me where I am wrong. My value is reurning nil because I am not fetching it correctly. Here is my snippet and JSON.
#IBAction func getWeather(sender: AnyObject) {
let requestURL: NSURL = NSURL(string: "http://api.openweathermap.org/data/2.5/weather?lat=35&lon=139&appid=MYAPPID")!
let urlRequest: NSMutableURLRequest = NSMutableURLRequest(URL: requestURL)
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(urlRequest) {
(data, response, error) -> Void in
let httpResponse = response as! NSHTTPURLResponse
let statusCode = httpResponse.statusCode
if (statusCode == 200) {
print("JSON Downloaded Sucessfully.")
do{
let json = try NSJSONSerialization.JSONObjectWithData(data!, options:.AllowFragments)
if let today = json["weather"] as? [[String: AnyObject]] {
//this is pulling 4 key value pairs
for weather in today {
//this works
let id = weather["id"]?.stringValue
self.trumpDescription.text=id;
print(id)
//this is where I am confused it changes from an array to just an object
let temp = json["temp"] as? String
self.currentTempView.text=temp;
print(temp)
}
}
}
catch {
print("Error with Json: \(error)")
}
}
}
task.resume()
}`
Here is the JSON:
{
"coord": {
"lon": 138.93,
"lat": 34.97
},
"weather": [
{
"id": 803,
"main": "Clouds",
"description": "broken clouds",
"icon": "04n"
}
],
"base": "cmc stations",
"main": {
"temp": 292.581,
"pressure": 1019.48,
"humidity": 99,
"temp_min": 292.581,
"temp_max": 292.581,
"sea_level": 1028.92,
"grnd_level": 1019.48
},
"wind": {
"speed": 5.36,
"deg": 237.505
},
"clouds": {
"all": 64
},
"dt": 1464964606,
"sys": {
"message": 0.0037,
"country": "JP",
"sunrise": 1464895855,
"sunset": 1464947666
},
"id": 1851632,
"name": "Shuzenji",
"cod": 200
}
It looks like it should be
if let main = json["main"] as? NSDictionary {
let temp = main["temp"] as! String
print(temp)
}
Instead of this:
let temp = json["temp"] as? String
Try this:
if let main = json["main"] as? [String: AnyObject] {
let temp = main[temp]?.stringValue
print(temp)
//alternatively you can try this as per your convenience of data type
let tempNew = main[temp]?.doubleValue
print(tempNew)
}
I try to parse a response which return a valid JSON with NSJSonSerialization. But it returns nil with no error. It works with another JSON response.
I did some search, and this could be a problem with the encoding of the JSON. I don't know how to solve it. Any idea ?
let url: NSURL = NSURL(string: urlPath)!
self.searchRequest = NSMutableURLRequest(URL: url)
if let searchRequest = self.searchRequest {
searchRequest.HTTPMethod = "GET"
let authString : String = SNCF.APIKey + ":" + ""
let authData : NSData = authString.dataUsingEncoding(NSASCIIStringEncoding)!
let authValue : String = "Basic " + authData.base64EncodedStringWithOptions(.EncodingEndLineWithCarriageReturn)
searchRequest.setValue(authValue, forHTTPHeaderField: "Authorization")
let queue:NSOperationQueue = NSOperationQueue()
NSURLConnection.sendAsynchronousRequest(searchRequest, queue: queue, completionHandler:{ (response: NSURLResponse?, data: NSData?, error: NSError?) -> Void in
do {
//HERE JSONRESULT WILL BE NIL
if let jsonResult = try NSJSONSerialization.JSONObjectWithData(data!, options: []) as? [String: [AnyObject]] {
print("ASynchronous\(jsonResult)")
if let places = jsonResult["stop_areas"] as? [[String:AnyObject]]{
for placeDictionary in places {
if let labelText = placeDictionary["label"] as? String {
self.resultDatasource.append(labelText)
}
}
self.resultTableView.reloadData()
}
}
//HERE NO ERROR IS CATCHED
} catch let error as NSError {
print(error.localizedDescription)
}
})
Piece of my json response :
{
"disruptions": [],
"pagination": {
"start_page": 0,
"items_on_page": 100,
"items_per_page": 100,
"total_result": 3053
},
"stop_areas": [
{
"codes": [
{
"type": "CR-CI-CH",
"value": "0080-251967-BV"
}
],
"name": "gare de Perl",
"links": [],
"coord": {
"lat": "0",
"lon": "0"
},
"label": "gare de Perl",
"timezone": "Europe/Paris",
"id": "stop_area:OCE:SA:80251967"
},
{
...
},
//stop_areas dictionaries object...
], //end stop_areas array of dictionaries
"links": [
{
"href": "https://api.sncf.com/v1/coverage/sncf/stop_areas/{stop_areas.id}",
"type": "stop_areas",
"rel": "stop_areas",
"templated": true
},
{
"href": "https://api.sncf.com/v1/coverage/sncf/stop_areas?start_page=1",
"type": "next",
"templated": false
},
{
"href": "https://api.sncf.com/v1/coverage/sncf/stop_areas?start_page=30.52",
"type": "last",
"templated": false
},
{
"href": "https://api.sncf.com/v1/coverage/sncf/stop_areas",
"type": "first",
"templated": false
}
],
"feed_publishers": [
{
"url": "",
"id": "sncf",
"license": "",
"name": ""
}
]
}
The type of the JSON is [String: AnyObject] not [String: [AnyObject]]
I think this is the problem:
as? [String: [AnyObject]]
Try to remove the cast. If your JSON is correct and has no validation errors, the dictionary you get probably has the key value of type Any. You can try to use the dictionary by only casting the value keys you want:
if let jsonResult = try NSJSONSerialization.JSONObjectWithData(data!, options: nil) {
print("ASynchronous\(jsonResult)")
if let places = jsonResult["stop_areas"] as? [[String:AnyObject]] {
...
}
}
Try This
do {
if let jsonResult: Dictionary = try NSJSONSerialization.JSONObjectWithData(self.mutableData, options: NSJSONReadingOptions.MutableContainers) as? Dictionary<String, AnyObject>
{
// print("get Read messages == \(jsonResult)");
if ((jsonResult["Warning"]) != nil)
{
let error_by_wc: NSString = jsonResult["Warning"] as! String
//print("results == \(error_by_wc)");
// printMessage("\(error_by_wc)")
JLToast.makeText("\(error_by_wc)").show()
}else if((jsonResult["Error"]) != nil)
{
let error_by_wc: NSString = jsonResult["Error"] as! String
// print("results == \(error_by_wc)");
// printMessage("\(error_by_wc)")
JLToast.makeText("\(error_by_wc)").show()
}
else
{
// read message s
}
} catch {
print(error)
}
If Data is Array Type Use this code
do {
if let jsonResult:NSArray = try NSJSONSerialization.JSONObjectWithData(self.mutableData, options: .MutableContainers) as? NSArray {
//print(jsonResult)
aDataBase.insertFromUserImage(jsonResult)
connection_allMEssages()
}else
{
//print("not data found")
BProgressHUD.dismissHUD(0)
}
} catch {
print(error)
BProgressHUD.dismissHUD(0)
}
On the below method, I can get the place value but not the location value. how can I get the location?
Thank you in advance!!
func searchDB(looking: String){
var urlString:String = "URLGOESHERE?q=\(looking)"
let url = NSURL(string: urlString)
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithURL(url!, completionHandler: { (data, response, error) -> Void in
if error != nil {
println(error)
}
else {
//processing data
if let arr = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: nil) as? [AnyObject] {
for currPlace in arr {
println(currPlace["name"])
println(currPlace["location"])
}
}
else {
errorOccurred = true
}
}//eo potential data
})
task.resume()
}//eom
This is the result output I am getting:
Optional(Buddha-Bar)
Optional(nil)
JSON sample:
sample data:
{
"formatted_address": "8-12 Rue Boissy d'Anglas, 75008 Paris, France",
"geometry": {
"location": {
"lat": 48.868194,
"lng": 2.321596
}
},
"icon": "http://maps.gstatic.com/mapfiles/place_api/icons/bar-71.png",
"id": "560dd225114fd10997f75ee777bad84bcb40c529",
"name": "Buddha-Bar",
"opening_hours": {
"open_now": true,
"weekday_text": []
},
"photos": [
{
"height": 848,
"html_attributions": [],
"photo_reference": "CnRnAAAAifUh9MiqwAgQYdwEp-EnS4e_nPQN_mPYIqdI49UKun_CZKxgtUh_ZqT8QBEqBuel9seoZvyyIVvA5-TlweEqO9_2tORg_cmTi_Cy5L_PAthdZd1_Krqbf7oJNy81RWD3brA8fzeIKJfQTMgo-AT19RIQAg5kKSqeoeedm69uhUWKvBoULDJ1-PoSgv4Lsg5y1rjU_pHm_Ng",
"width": 1919
}
],
"place_id": "ChIJRS81ac1v5kcRRUqQBmTTJJU",
"price_level": 3,
"rating": 3.7,
"reference": "CmReAAAAjJskNN69nw3gBVtqLpsX11Psr-QvK6cHPLhF-oDXAbYq7dwLn65b1svUJOLVnRgAbg4K3w7qCj9_hkXvx20q4YNR2714ZQQw89GyFGCtXAxonRh09_uvgK97DewsYRyUEhAczR_GzOvU0mmG1OZr0X3kGhQeJ1Vr3RSnI6VXyzh83W_LIcUK_g",
"types": [
"bar",
"restaurant",
"food",
"establishment"
]
},
Json data without spaces
sample data:
{
"formatted_address": "8-12 Rue Boissy d'Anglas, 75008 Paris, France",
"geometry": {
"location": {
"lat": 48.868194,
"lng": 2.321596
}
},
"icon": "http://maps.gstatic.com/mapfiles/place_api/icons/bar-71.png",
"id": "560dd225114fd10997f75ee777bad84bcb40c529",
"name": "Buddha-Bar",
"opening_hours": {
"open_now": true,
"weekday_text": []
},
"photos": [
{
"height": 848,
"html_attributions": [],
"photo_reference": "CnRnAAAAifUh9MiqwAgQYdwEp-EnS4e_nPQN_mPYIqdI49UKun_CZKxgtUh_ZqT8QBEqBuel9seoZvyyIVvA5-TlweEqO9_2tORg_cmTi_Cy5L_PAthdZd1_Krqbf7oJNy81RWD3brA8fzeIKJfQTMgo-AT19RIQAg5kKSqeoeedm69uhUWKvBoULDJ1-PoSgv4Lsg5y1rjU_pHm_Ng",
"width": 1919
}
],
"place_id": "ChIJRS81ac1v5kcRRUqQBmTTJJU",
"price_level": 3,
"rating": 3.7,
"reference": "CmReAAAAjJskNN69nw3gBVtqLpsX11Psr-QvK6cHPLhF-oDXAbYq7dwLn65b1svUJOLVnRgAbg4K3w7qCj9_hkXvx20q4YNR2714ZQQw89GyFGCtXAxonRh09_uvgK97DewsYRyUEhAczR_GzOvU0mmG1OZr0X3kGhQeJ1Vr3RSnI6VXyzh83W_LIcUK_g",
"types": [
"bar",
"restaurant",
"food",
"establishment"
]
},
Adding a little formatting to the pertinent part of the data:
sample data: {
"formatted_address": "8-12 Rue Boissy d'Anglas, 75008 Paris, France",
"geometry": {
"location": {
"lat": 48.868194,
"lng": 2.321596
}
},
"icon": "http://maps.gstatic.com/mapfiles/place_api/icons/bar-71.png",
"id": "560dd225114fd10997f75ee777bad84bcb40c529",
"name": "Buddha-Bar",
It is unclear what "sample data:" means as it is not quoted, it may be something added by the print statement (my guess) in which case it is not needed to access the components.
The name would be addresses as:
["name"]
The location is in lat/lon so there will be two accesses:
["geometry"]["location"]["lat"]
["geometry"]["location"]["lon"]
In the above the applicable language syntax must be applied, in Swift there will be some pain.
See json.org for information on JSON.
After some frustration and game of thrones. the messy solution was the one below.
an alternative may be api like
https://github.com/lingoer/SwiftyJSON
func searchDB(looking: String){
var errorOccurred:Bool = false
var urlString:String = "URLGOESHERE?q=\(looking)"
let url = NSURL(string: urlString)
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithURL(url!, completionHandler: { (data, response, error) -> Void in
if error != nil {
println(error)
errorOccurred = true
} else {
// println(response) //response from post
//processing data
let jsonObject : AnyObject! = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil)
if let statusesArray = jsonObject as? NSArray{
println("********* LEVEL 1 *******")
println(statusesArray[0])
if let aStatus = statusesArray[0] as? NSDictionary{
println("********* LEVEL 2 *******")
println(aStatus)
if let geometry = aStatus["geometry"] as? NSDictionary{
println("********* LEVEL 3 *******")
println(geometry)
if let currLocation = geometry["location"] as? NSDictionary{
println("********* LEVEL 4 *******")
println(currLocation)
println(currLocation["lat"])
println(currLocation["lng"])
}
}
}
}
else {
errorOccurred = true
}
}//eo potential data
})
task.resume()
}//eom