JSON SWIFT, how to access the values - json

i have the following Json
USD {
"avg_12h" = "8252.96";
"avg_1h" = "8420.80";
"avg_24h" = "8253.11";
"avg_6h" = "8250.76";
rates = {
last = "8635.50";
};
"volume_btc" = "76.05988903";
}
where USD is a key found after searching in a json file, i want to access "avg_12h" value and assign it to a variable, what is the best way to do it.
import UIKit
/*URLSessionConfiguration.default
URLSessionConfiguration.ephemeral
URLSessionConfiguration.background(withIdentifier: <#T##String#>)
// create a URLSession instance
let config = URLSessionConfiguration.default
let session = URLSession(configuration: config)*/
/*create a URLSession instance*/
let config = URLSessionConfiguration.default
let session = URLSession(configuration: config)
/*
The session.dataTask(with: url) method will perform a GET request to the url specified and its completion block
({ data, response, error in }) will be executed once response is received from the server.*/
let url = URL(string: "https://localbitcoins.com/bitcoinaverage/ticker-all-currencies")!
let task = session.dataTask(with: url) { data, response, error in
// ensure there is no error for this HTTP response
guard error == nil else {
print ("error: \(error!)")
return
}
// ensure there is data returned from this HTTP response
guard let content = data else {
print("No data")
return
}
/*JSONSerialization.jsonObject(with: content,
options: JSONSerialization.ReadingOptions.mutableContainers) as?
[String: Any] will parse the JSON data returned from web server into a dictionary*/
// serialise the data / NSData object into Dictionary [String : Any]
guard let json = (try? JSONSerialization.jsonObject(with: content, options: JSONSerialization.ReadingOptions.mutableContainers)) as? [String: Any] else {
print("Not containing JSON")
return
}
let bolivares = "VES"
for (key, value) in json {
if key==bolivares {
print(value)
//ADD CODE TO ACCESS avg_12h and assign it to a value
}
}
}
// update UI using the response here
// execute the HTTP request
task.resume()

Assuming you are receiving the JSON as raw data and it hasn't been converted to an object yet, ou would want to do something like the following:
guard let jsonObject = try? JSONSerialization.jsonObject(with: data, options: []) as! [String:[String]] else { return }
let usd = jsonObject["USD"]
let avg_12h = usd["avg_12h"]
But this will only work based on some assumptions I've made about the JSON you've provided. Is there a way you can link to a paste of the full JSON file?

Create two simple structs to hold your data (I didn't add all fields here)
struct PriceInfo {
let avg12h: String
let avg1h: String
let rates: [Rate]
}
struct Rate {
let last: String
}
then after converting json you can map it to a dictionary of [String: PriceInfo] where the key is the currency code
do {
if let json = try JSONSerialization.jsonObject(with: content) as? [String: Any] {
let prices: [String: PriceInfo] = json.mapValues {
let dict = $0 as? [String: Any]
let avg12h = dict?["avg_12h"] as? String ?? ""
let avg1h = dict?["avg_1h"] as? String ?? ""
let rates = dict?["rates"] as? [String: String] ?? [:]
return PriceInfo(avg12h: avg12h, avg1h: avg1h, rates: rates.compactMap { rate in Rate(last: rate.value) } )
}
}
} catch {
print(error)
return
}

Try to use CodingKey, it will be more clearer and JSONDecoder().decode method. I assume that you use any JsonViewer

Related

How do I get my Swift code to read a specific piece of information from the JSON file

I am trying to read the data for "Name" in a JSON file I am hosting using Swift and I seem to only be able to read the whole JSON file and not able to pick out specific data. My JSON file contains this:
[{"Email":"Admin#admin.com","Password":"password","Name":"Admin"}]
The swift code I am using is this:
override func viewDidLoad() {
super.viewDidLoad()
//to get data from external DB
let url = URL(string: "http://localhost/Projects/Test_mobileAPI/test_userInfo.php?email=Admin#admin.com")
let task = URLSession.shared.dataTask(with: url!) { (data, response, error) in
if error != nil{
print("Error Occured")
}
else{
print("Okie")
if let content = data {
do{
//Array
let myJson = try JSONSerialization.jsonObject(with: content, options: JSONSerialization.ReadingOptions.mutableContainers) as AnyObject
print("this part works")
print(myJson)
if let diction = myJson as? NSDictionary
{
if let name = myJson["Name"]{
print(name as Any)
}
}
}
catch{
print(error)
}
}
}
}
task.resume()
}
The output I keep getting is this:
Okie
this part works
(
{
Email = "Admin#admin.com";
Name = Admin;
Password = password;
}
)
But I do not get just the value for "Name". Can anyone help me get the value for "Name" (i.e "Admin")
Can you try
if let myJson = try JSONSerialization.jsonObject(with: content) as? [[String:Any]] {
if let first = myJson.first {
print(first["Name"])
}
}
The problem is that the JSON that you're receiving back isn't a Dictionary, it's a single element array with a dictionary in it. So when you do
if let diction = myJson as? NSDictionary
the myJson object is failing the cast to NSDictionary. If you unwrap the array first, you should then be able to reference the dictionary and pick off any keyed values you want:
if let array = myJson as? NSArray
{
if let myDict = array[0] as? NSDictionary
{
if let name = myDict ["Name"]{
print(name as Any)
}
}
}

Load data from server using swift 4

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()

HTTP Request GET JSON and read data

i have a problem by a code of me in swift. I do a request to webserver by httpMethod POST. This request is ok. I get a response and data inside the data value. The data looks like JSON
{"pushValues": {"devicePushGlobal":"1","devicePushNewProducts":"1","devicePushNewOffer":"1"}}
Then I will load this response data to set buttons based on the response data. But i fail to write this code. Can someone help me please? :)
Error Code
Cannot invoke 'jsonObject' with an argument list of type '(with: NSString)'
// i tested with other options but i always fail :-(
I comment the error in the code ....
let url = "https://URL.php"
let request = NSMutableURLRequest(url: NSURL(string: url)! as URL)
let bodyData = "token=" + (dts)
request.httpMethod = "POST"
request.httpBody = bodyData.data(using: String.Encoding.utf8);
NSURLConnection.sendAsynchronousRequest(request as URLRequest, queue: OperationQueue.main) {
(response, data, error) in
// here i get the result of
// {"pushValues": {"devicePushGlobal":"1","devicePushNewProducts":"1","devicePushNewOffer":"1"}}
var str = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
var names = [String]()
// here i will get each value of pushValues to add to the array names
do {
if let data = str,
// ... and here is the error code by xcode ::: ==> Cannot invoke 'jsonObject' with an argument list of type '(with: NSString)'
// i tested with other options but i always fail :-(
let json = try JSONSerialization.jsonObject(with: data) as? [String: Any],
let blogs = json["pushValues"] as? [[String: Any]] {
for blog in blogs {
if let name = blog["devicePushGlobal"] as? String {
print(name)
names.append(name)
}
}
}
} catch {
print("Error deserializing JSON: \(error)")
}
// names array is empty
print(names)
}
Thank you for your help
You shouldn't decode the JSON response into an NSString using var str = NSString(data: data!, encoding: String.Encoding.utf8.rawValue). JSONSerialization.jsonObject() expects a Data object as an input argument, so just safely unwrap the optional data variable and use that as the input argument:
if let responesData = data, let json = try JSONSerialization.jsonObject(with: responseData) as? [String: Any], let blogs = json["pushValues"] as? [String: Any]
The full code using native Swift types:
...
let request = URLRequest(url: URL(string: url)!)
...
URLSession.shared.dataTask(with: request, completionHandler: {
(response, data, error) in
var names = [String]()
do {
if let responseData = data, let json = try JSONSerialization.jsonObject(with: responseData) as? [String: Any], let blogs = json["pushValues"] as? [String: Any]{
if let name = blog["devicePushGlobal"] as? Int {
print(name)
names.append(name)
}
if let newProducts = blog["devicePushNewProducts"] as? Int{}
if let newOffers = blog["devicePushNewOffers"] as? Int{}
}
} catch {
print("Error deserializing JSON: \(error)")
}
// names array is empty
print(names)
}).resume()

Error while parsing JSON in Swift, [String:Any] won't work

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?
}

How do I get a specific value from returned json in Swift 3.0?

I am trying to get a value from json in Swift. I have added an image of the data tree. My previous attempts have not worked. Below is code which prints the full json object which is what I don't want.
json tree image
import PlaygroundSupport
import UIKit
let url = URL(string: "https://api.data.gov.sg/v1/transport/taxi-availability")
var request = URLRequest(url: url!);
request.addValue("xxxx", forHTTPHeaderField: "api-key")
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard error == nil else {
print(error)
return
}
guard let data = data else {
print("Data is empty")
return
}
let json = try! JSONSerialization.jsonObject(with: data, options: [])
//print(json)
}//end
//["features"]??[0]?
task.resume()
PlaygroundPage.current.needsIndefiniteExecution = true
You just need to do something with the json you've been vended:
let task = URLSession ... { data, response, error in
let json = JSONSerialization.jsonObject(...)
if let json = json as? [String: Any] {
// now you have a top-level json dictionary
for key, value in json {
print("json[\"\(key\")] = \(value)")
}
}
}
I didn't verify the following code but it should work for the son tree you provided. (disclaimer: might have some errors but its mostly correct)
if let json = (try? JSONSerialization.jsonObject(with: data, options: [])) as? [String:Any]
, let features = json["features"] as? [Any]
, let firstFeature = features[0] as? [String:Any]
, let properties = firstFeature["properties"] as? [String:Any]
, let taxiCount = properties["taxi_count"] as? Int
{
print(taxiCount)
}
If Json is dictionary
let json = try! JSONSerialization.jsonObject(with: data, options: [])
let jsonDict = json as? NSDictionary
//if you have a key name
let name = jsonDict["name"] as? String
//and so on
//if you have a array in your dictionary
let likes = jsonDict["likes"] as? NSArray
let numberOfLikes = likes.count
for eachLike in likes {
let likerName = eachLike["liker_name"] as? String
}