I've been trying to find out how to save a part of a JSON response from Alamofire as a variable to make an if statement and can't seem to find how to do it.
I made a piece of code to use as an example for the question which consists of the following:
import UIKit
import Alamofire
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
Alamofire.request("http://api.openweathermap.org/data/2.5/weather?q=London,uk&appid=44143256ee15e9c3f521ca062463dd8d").responseJSON { response in
print(response.result) // result of response serialization
if let JSON = response.result.value {
print("JSON: \(JSON)")
}
}
}
}
I get the following response from the API request:
JSON: {
base = stations;
clouds = {
all = 0;
};
cod = 200;
coord = {
lat = "51.51";
lon = "-0.13";
};
dt = 1485031800;
id = 2643743;
main = {
humidity = 83;
pressure = 1026;
temp = "270.54";
"temp_max" = "273.15";
"temp_min" = "267.15";
};
name = London;
sys = {
country = GB;
id = 5091;
message = "0.0038";
sunrise = 1484985141;
sunset = 1485016345;
type = 1;
};
visibility = 7000;
weather = (
{
description = haze;
icon = 50n;
id = 721;
main = Haze;
}
);
wind = {
speed = 1;
};
}
From this JSON response I would like to save the weather description so I could use the following statement:
if var currentWeather = sunny {
return "Nice day!"
} else {
return "Uh-Oh, keep warm!"
}
If anyone could help me with this I would greatly appreciate it! If I have to use SwiftyJSON to make it easier that's fine I've just been struggling with this for a while and need to figure it out!
You can parse your result following the printout of your JSON response:
guard let JSON = response.result.value as? [String:Any],
let weather = JSON["weather"] as? [[String:Any]] else {
print("Could not parse weather values")
return
}
for element in weather {
if let description = element["description"] as? String {
print(description)
}
}
If you wanted to save the result, or do something based on a certain result as you described, you could insert something else instead of just print(description) like:
if description == "sunny" {
//do something
}
Let me know if this makes sense. Keep in mind that ( and ) in the Xcode console means "Array".
Related
Following is the code which i used Alamofire to call a GET api for getting the train details:
var url:String!
url = "https://api.railwayapi.com/v2/name-number/train/bhopal/apikey/iixp5yxd/"
Alamofire.request(url, method: .get, encoding: JSONEncoding.default)
.responseJSON { response in
switch response.result {
case .success(let json):
print(json)
if let json = response.result.value as? [String:Any] {
print(json["train"]!)
if let nestedDictionary1 = json["train"] as? [String: AnyObject] {
// access individual value in dictionary
if let views = nestedDictionary1["number"] as? String {
print(views)
}
if let classes = nestedDictionary1["classes"] as? [String: AnyObject] {
print(classes)
}
}
}
DispatchQueue.main.async {
// handle your code
}
case .failure(let error):
print(error)
}
}
At the print(json) line i am getting the following JSON response as:
{
debit = 1;
"response_code" = 200;
train = {
classes = (
{
available = N;
code = 2S;
name = "SECOND SEATING";
},
{
available = N;
code = FC;
name = "FIRST CLASS";
},
{
available = Y;
code = 2A;
name = "SECOND AC";
},
{
available = N;
code = 3E;
name = "3rd AC ECONOMY";
},
{
available = Y;
code = SL;
name = "SLEEPER CLASS";
},
{
available = N;
code = CC;
name = "AC CHAIR CAR";
},
{
available = Y;
code = 3A;
name = "THIRD AC";
},
{
available = Y;
code = 1A;
name = "FIRST AC";
}
);
days = (
{
code = MON;
runs = Y;
},
{
code = TUE;
runs = Y;
},
{
code = WED;
runs = Y;
},
{
code = THU;
runs = Y;
},
{
code = FRI;
runs = Y;
},
{
code = SAT;
runs = Y;
},
{
code = SUN;
runs = Y;
}
);
name = "SHAN-E- BHOPAL EXP";
number = 12156;
};
}
How shall i extract the value of key "Classes" and the corresponding keys of "Classes" . I used this in the above code , but unfortunately its not working:
if let classes = nestedDictionary1["classes"] as? [String: AnyObject] {
print(classes)
}
Since i am a newbie to the Alamofire please tell where i am getting wrong and how to solve this?
Please read the output. JSON has only two collection types, array [] (in the output ()) and dictionary {}.
So the value for key classes is clearly an array ([[String:Any]]) and JSON unspecified values are always Any, never AnyObject.
And please use more descriptive variable names.
if let json = response.result.value as? [String:Any] {
if let train = json["train"] as? [String: Any] {
print(train)
// access individual value in dictionary
if let number = train["number"] as? String { // more likely `Int`
print(number)
}
if let classes = train["classes"] as? [[String: Any]] {
for aClass in classes {
let name = aClass["name"] as! String
let available = aClass["available"] as! String
print(name, available)
}
}
}
}
Nevertheless consider to use the Codable protocol. It's more convenient and more efficient
Hello I'm new to swift and this is giving me some problems.
I have a function from SDK that returns Any as a result, this is what the actual data looks like:
/*{
code = 1;
msg = success;
result = {
macAddress = "E6:1D:4D:71:64:9B";
};
}*/
I figured out a way to get the data I need, but it seems quite convoluted.
sucBlock: {
(mac) in
if let macAddress = ((mac as AnyObject)["result"] as AnyObject )["macAddress"] as! Optional<String>{
print("macAddress:" + macAddress)
}
}
Is there a better way to achieve this result? I tried to create a struct and type cast this object, but somehow it always failed.
You need to avoid using AnyObject and as! in such cases
if let macAddress = mac as? [String:Any] , let item = macAddress["result"] as? [String:String] , let str = item["macAddress"] {
print("str:" + str)
}
If you need a struct ( Don't think it really deserves for your simple json )
do {
let data = try JSONSerialization.data(withJSONObject:mac)
let res = try JSONDecoder().decode(Root.self, from:data)
print(res.result.macAddress)
}
catch {
print(error)
}
struct Root: Codable {
let code: Int
let msg: String
let result: Result
}
// MARK: - Result
struct Result: Codable {
let macAddress: String
}
I'm trying to use JSONDecoder with FirebaseDatabase. There are some examples online, but I haven't been able to find one with dynamic object keys like the ones that are being returned in the response I am getting. Is there a better way to do this?
JSON Example:
{
"-LUOhAM5W42t9YxqFkUQ" = {
author = {
name = testName;
};
commentCount = 0;
detail = "";
id = "-LUOhAM5W42t9YxqFkUQ";
likeCount = 0;
};
"-LUOhNU4wfwTlZQkrGFu" = {
author = {
name = otherName;
};
commentCount = 0;
detail = "";
id = "-LUOhNU4wfwTlZQkrGFu";
likeCount = 0;
};
My Struct looks like this (I'm just trying to decode successfully first):
struct Post: Decodable {
var id: String?
var title: String?
}
And my code in my controller looks like this:
func getPosts() {
Database.database().reference().child("posts").observeSingleEvent(of: .value, with: { (snapshot) in
guard let value = snapshot.value else { return }
print("VALUE: \(value)")
do {
let person = try FirebaseDecoder().decode(Post.self, from: value)
print(person)
} catch let error {
print(error)
}
})
}
I know I could loop through each object, decode and then add them to an array, but I'm looking for the most efficient approach and I really like the JSONDecoder. Again, the snag seems to be that Firebase puts the object key at the beginning of each object, which seems weird. Any help at all would be greatly appreciated!
How to use values globally parsed from JSONResponse. So, far able to extract the array from JSONResponse, but after that trying to put that array in an global array, not getting how to declare global array. somehow managed to do that but now not able to extract values index wise from that array. Please guide.
Code tried now:
if (JSONResponse["status"].intValue == 1)
{
if let fetchedImages = JSONResponse["data"].arrayObject {
self.arrResponseReceived = fetchedImages
}
print("self.arrResponseReceived", self.arrResponseReceived)
}
else
{
CommonMethodsClass.showAlertMessage(vc: self, titleStr: "Error!", messageStr: strMsg)
}
Code tried earlier:
arrResponseReceived = JSONResponse["data"].arrayValue
Global variable declared for array is:
var arrResponseReceived : [Any] = []
Data to parse is:
{
data = (
{
AverageRating = 4;
Image = "<null>";
IsActive = 1;
Latitude = "28.567806";
Longitude = "77.3236273";
SalonAddress = " Sec-58, India";
SalonEmail = "vy.chan#th-rce.com";
SalonID = 1;
SalonImage = "";
SalonMobile = 9999888877;
SalonName = Affinity;
SalonPhone = 9999888877;
TimeIntervalminutes = 20;
},
{
AverageRating = 5;
Image = "<null>";
IsActive = 1;
Latitude = "";
Longitude = "";
SalonAddress = "Mall, India";
SalonEmail = "rad#th-rce.com";
SalonID = 3;
SalonImage = "";
SalonMobile = 9999888877;
SalonName = Looks;
SalonPhone = 9999888877;
TimeIntervalminutes = 30;
}
);
message = "";
status = 1;
}
You should definite the Class of what is inside of JSONResponse["data"].arrayValue, or how Xcode knows it.
If you want to get an data array which is made of Dictionary , here is how I cheated it out.
func getDatas(from json: Any?) -> [Dictionary] {
guard let json = json as? NSDictionary, let entries = json.value(forKeyPath: "data") as? [NSDictionary] else {
return []
}
return entries.flatMap { entry in
guard let dictionary = entry as? NSDictionary else {
return nil
}
return dictionary
}
}
you call it as such
self.arrResponseReceived = getDatas(from: json)
NSDictionary has the method value(forKeyPath:) that is near magic. Calling json.value(forKeyPath: "data") returns an array of dictionaries. Each dictionary is an "entry" object in the json. Next, I map each entry which returns a dictionary.
If this is something more than a quick solution, then I would consider adding SwiftyJSON to your project.
func getDatas(from json: Any?) -> [Dicitonary] {
return JSON(json)["data"].arrayValue.flatMap { entry in
guard let dictionary = entry as? NSDictionary else {
return nil
}
return dictionary
}
}
I am trying to get NBA standings from this website https://erikberg.com/api
To do this, I am using AlmoFire to make a Get request:
Alamofire.request(.GET, "https://erikberg.com/nba/standings.json")
.responseJSON { response in
print(response.2.value)
}
What this is returning is a response array with a NSURLRequest at index 0, an NSHTTPURLResponse at index 1, and a result of type AnyObject at index 2. The AnyObject, when printed, results in this (I'm only showing one team because the array is very long):
Optional({
standing = (
{
"away_lost" = 14;
"away_won" = 21;
conference = EAST;
"conference_lost" = 13;
"conference_won" = 29;
division = CEN;
"first_name" = Cleveland;
"games_back" = 0;
"games_played" = 71;
"home_lost" = 6;
"home_won" = 30;
"last_five" = "4-1";
"last_name" = Cavaliers;
"last_ten" = "7-3";
lost = 20;
"ordinal_rank" = 1st;
"playoff_seed" = 1;
"point_differential" = 437;
"point_differential_per_game" = "6.2";
"points_against" = 6948;
"points_allowed_per_game" = "97.9";
"points_for" = 7385;
"points_scored_per_game" = "104.0";
rank = 1;
streak = W2;
"streak_total" = 2;
"streak_type" = win;
"team_id" = "cleveland-cavaliers";
"win_percentage" = ".718";
won = 51;
},exc...
I would like to know how I can parse this data so I can extract and categorize each team based on their standings.
Thank you
You can use ObjectMapper to parse JSON. Make a Standing class which contains all the JSON to object mapping code.
class Standing: Mappable {
var awayLost: Int?
var awayWon: Int?
..... // Define all variables
required init?(_ map: Map) {}
// This function is used to map all variables to corresponding JSON strings
func mapping(map: Map) {
awayLost <- map["away_lost"]
awayWon <- map["away_won"]
...
}
Similarly, make a parent class to hold array of standing.
class ParentJson: Mappable {
var standingsDate: String?
var standing: [Standing]
}
func mapping(map: Map) {
standing <- map["standing"]
}
And then in your alamofire response, map the corresponding class
Alamofire.request(.GET, "https://erikberg.com/nba/standings.json")
.responseJSON { response in
let parentJson = Mapper<ParentJson>().map(response.2.value)
let standingsArray: [Standing] = parentJson.standing
standingArray will now have all the data required to categorize.
I use the SwiftyJSON package for all things JSON related. Then, you can use this idiom
.responseJSON { response in
switch response.result {
case .Success:
if let value = response.result.value {
let json = JSON(value)
if let datum = json["field"].string { // Depending on expected type; see docs
}
case .Failure(let error):
print(error)
}