Parsing my SWIFT Dictionary - ios

I am querying a JSON database of zombies and it returns them as a Dictionary. I don't know how to mutate it with SWIFT 3
Here's the query::
func getZombieAttackGroupFromDatabase () {
ref?.child("Attacker Group").child((self.userParty?.leadID)!).observeSingleEvent(of: .value, with: { (snapshot) in
// Get data
print("PULLING DATA")
if let value = snapshot.value as? NSDictionary{
// break data into an Array of Zombie Structs
// print(value)
for zombieID in value.allKeys {
print(value[zombieID])
let thisZombieID = zombieID
let thisZombieGroup = value[zombieID]["Group"]
}
} else {
}
// ...
}) { (error) in
print(error.localizedDescription)
}
}
this part: let thisZombieGroup = value[zombieID]["Group"] isn't being recognized. How do I access group? If i get that, i can modify to the other components.
Here's the return :
{
"-KrNSmv64Ia32g5nw1L9" = {
Group = 15;
Health = 250;
"Is Undead" = true;
Location = 1;
Number = 0;
};
"-KrNSmv64Ia32g5nw1LA" = {
Group = 11;
Health = 250;
"Is Undead" = true;
Location = 5;
Number = 1;
};
"-KrNSmv64Ia32g5nw1LB" = {
Group = 2;
Health = 250;
"Is Undead" = true;
Location = 3;
Number = 2;
};
"-KrNSmv776r9eO6t7CY0" = {
Group = 14;
Health = 250;
"Is Undead" = true;
Location = 0;
Number = 3;
};
"-KrNSmv776r9eO6t7CY1" = {
Group = 0;
Health = 250;
"Is Undead" = true;
Location = 4;
Number = 4;
};
}
As you can see, each of the Structs has a parent that is an automatically generated ID. I don't know how to access it.
How can I access each element from item 1? I need the parent auto-key "-KrNSmv64Ia32g5nw1L9" and each child value.
"-KrNSmv64Ia32g5nw1L9" = {
Group = 15;
Health = 250;
"Is Undead" = true;
Location = 1;
Number = 0;

Cast value to a proper Swift dictionary, not NSDictionary.
if let value = snapshot.value as? [String:Any].
You just have to iterate through the keys of the dictionaries, get the embedded dictionary using the key value and then parse the "zombie data".
for key in value.keys {
if let zombieData = value[key] as? [String:Any] {
zombieData
if let group = zombieData["Group"] as? Int, let health = zombieData["Health"] as? Int, let isUndead = zombieData["Is Undead"] as? Bool, let location = zombieData["Location"] as? Int, let number = zombieData["Number"] as? Int {
//use the parsed data
}
}
}

Try this:
for zombieID in value.allKeys {
print(value[zombieID])
let thisZombieID = zombieID
if let zombieValues = value[zombieID] as? [String:Any] {
let thisZombieGroup = zombieValues["Group"] as? Int
}
}

First, Thank you so much to Woof and David. It was a combination of both of your ideas that got it to work.
func getZombieAttackGroupFromDatabase () {
ref?.child("Attacker Group").child((self.userParty?.leadID)!).observeSingleEvent(of: .value, with: { (snapshot) in
// Get data
print("PULLING DATA")
if let value = snapshot.value as? [String:Any]{
// break data into an Array of Zombie Structs
for zombieID in value.keys {
let thisZombieID = zombieID
print(thisZombieID)
let zombieValues = value[zombieID] as? [String:Any]
let thisZombieGroup = zombieValues?["Group"] as! String
print(thisZombieGroup)
}
} else {
}
// ...
}) { (error) in
print(error.localizedDescription)
}
}
}

Related

Could not cast value of type '__NSSingleObjectArrayI' to 'NSDictionary' in Swift

When I parse the Api I got response and stored full response to Dictionary then I split it to array and dictionary, But I get error so please help to solve the error,
Here I give the code what I am tried.
let responseDictionary:NSDictionary = responseObject as! NSDictionary
print(responseDictionary)
if let statusCode:NSNumber = responseDictionary.value(forKey: "success") as? NSNumber{
if statusCode == 1{
print("statusCode :",statusCode)
let incomingRequetArray:NSArray = responseDictionary.value(forKey: "incoming_requests") as! NSArray
print("incomingRequetArray",incomingRequetArray)
if (incomingRequetArray.count > 0)
{
let requestDataDict:NSDictionary = incomingRequetArray.value(forKey: "request_data") as! NSDictionary -----> Error in this line
print("requestDataDict",requestDataDict)
let ownerArray:NSArray = requestDataDict.value(forKey: "owner") as! NSArray
print("ownerArray",ownerArray)
self.mutDictOwner = ownerArray.object(at: 0) as! NSMutableDictionary
}
}
responseDictionary is
"incoming_requests" = (
{
datetime = "2017-04-17 12:25:58";
later = 0;
"request_data" = {
dog = (
);
owner = {
address = "";
"d_latitude" = "0.00000000";
"d_longitude" = "0.00000000";
"dest_latitude" = "0.00000000";
"dest_longitude" = "0.00000000";
latitude = "11.01449160";
longitude = "76.98273220";
name = "Sss Sas";
"num_rating" = 0;
"payment_type" = 1;
phone = "+919123456789";
picture = "";
rating = "0.00";
};
"payment_mode" = 1;
};
"request_id" = 1474;
"request_services" = 30;
"time_left_to_respond" = 21;
}
);
"is_approved" = 1;
"is_approved_txt" = Approved;
"is_available" = 1;
success = 1;
It is because your "request_data" is an Object and not a Dictionary, see how "incoming_request" has started (with a " ( ") and "request_data" is starting with "{". what you can do to access is this
let requestDataDict:NSDictionary = incomingRequetArray.value(forKey: "request_data") as! [AnyObject]-----> Error in this line
print("requestDataDict",requestDataDict)
let x = requestDataDict[0] as! NSDictionary
let ownerArray:NSArray = x.value(forKey: "owner")as! NSArray
your are doing wrong incomingRequetArray is NSArray and you are getting value for key
Write this
let requestDataDict:NSDictionary = incomingRequetArray[0]as!NSDictionary
let newDict: NSDictionary = requestDataDict.object(forKey: "request_data")
print("newDict is ---%#", newDict)
you have used NSDictionary and NSArray format So I have written the code according to yours. But for further uses in swift Do not use NSDictionary and NSArray.
This is a reasonable Swift transcription which solves the error. It uses a type alias for convenience.
typealias JSONDictionary = [String:Any]
let responseDictionary = responseObject as! JSONDictionary
print(responseDictionary)
if let success = responseDictionary["success"] as? Int, success == 1 {
print("statusCode :", success)
let incomingRequestArray = responseDictionary["incoming_requests" as! [JSONDictionary]
print("incomingRequetArray",incomingRequestArray)
if let requestDataDict = incomingRequestArray.first {
print("requestDataDict",requestDataDict)
if let ownerArray = requestDataDict["owner"] as? [JSONDictionary], !ownerArray.isEmpty {
print("ownerArray",ownerArray)
self.mutDictOwner = ownerArray[0] as! JSONDictionary
}
}
In the line that's throwing an error try to change incomingRequetArray.value... to incomingRequetArray[0].value... as you need to access the internal dictionary that's contained in an array and then query for the value for given key.

Parsing JSON using a Swift Dictionary

I am having a hard time parsing JSON with Swift. I have written a function that make a get request to an api and retrieves the data as JSON and converts it into a dictionary. After that I am trying to use a tableViewController to set each title and subtitle from the values I received from the JSON. I am trying to set the title as the homeTeam and the subtitle as the awayTeam. I do not know much about Swift so I was hoping for some help.
Here is my JSON that is stored in a dictionary:
dictionary = ["scoreboard": {
gameScore = (
{
game = {
ID = 35119;
awayTeam = {
Abbreviation = ATL;
City = Atlanta;
ID = 91;
Name = Hawks;
};
date = "2017-04-07";
homeTeam = {
Abbreviation = CLE;
City = Cleveland;
ID = 86;
Name = Cavaliers;
};
location = "Quicken Loans Arena";
time = "7:30PM";
};
isCompleted = false;
isInProgress = false;
isUnplayed = true;
quarterSummary = "<null>";
},
{
game = {
ID = 35120;
awayTeam = {
Abbreviation = MIA;
City = Miami;
ID = 92;
Name = Heat;
};
date = "2017-04-07";
homeTeam = {
Abbreviation = TOR;
City = Toronto;
ID = 81;
Name = Raptors;
};
location = "Air Canada Centre";
time = "7:30PM";
};
isCompleted = false;
isInProgress = false;
isUnplayed = true;
quarterSummary = "<null>";
},
{
game = {
ID = 35121;
awayTeam = {
Abbreviation = NYK;
City = "New York";
ID = 83;
Name = Knicks;
};
date = "2017-04-07";
homeTeam = {
Abbreviation = MEM;
City = Memphis;
ID = 107;
Name = Grizzlies;
};
location = "FedEx Forum";
time = "8:00PM";
};
isCompleted = false;
isInProgress = false;
isUnplayed = true;
quarterSummary = "<null>";
},
{
game = {
ID = 35122;
awayTeam = {
Abbreviation = DET;
City = Detroit;
ID = 88;
Name = Pistons;
};
date = "2017-04-07";
homeTeam = {
Abbreviation = HOU;
City = Houston;
ID = 109;
Name = Rockets;
};
location = "Toyota Center";
time = "8:00PM";
};
isCompleted = false;
isInProgress = false;
isUnplayed = true;
quarterSummary = "<null>";
},
{
game = {
ID = 35123;
awayTeam = {
Abbreviation = SAS;
City = "San Antonio";
ID = 106;
Name = Spurs;
};
date = "2017-04-07";
homeTeam = {
Abbreviation = DAL;
City = Dallas;
ID = 108;
Name = Mavericks;
};
location = "American Airlines Center";
time = "8:30PM";
};
isCompleted = false;
isInProgress = false;
isUnplayed = true;
quarterSummary = "<null>";
},
{
game = {
ID = 35124;
awayTeam = {
Abbreviation = NOP;
City = "New Orleans";
ID = 110;
Name = Pelicans;
};
date = "2017-04-07";
homeTeam = {
Abbreviation = DEN;
City = Denver;
ID = 99;
Name = Nuggets;
};
location = "Pepsi Center";
time = "9:00PM";
};
isCompleted = false;
isInProgress = false;
isUnplayed = true;
quarterSummary = "<null>";
},
{
game = {
ID = 35125;
awayTeam = {
Abbreviation = MIN;
City = Minnesota;
ID = 100;
Name = Timberwolves;
};
date = "2017-04-07";
homeTeam = {
Abbreviation = UTA;
City = Utah;
ID = 98;
Name = Jazz;
};
location = "Vivint Smart Home Arena";
time = "9:00PM";
};
isCompleted = false;
isInProgress = false;
isUnplayed = true;
quarterSummary = "<null>";
},
{
game = {
ID = 35126;
awayTeam = {
Abbreviation = OKL;
City = "Oklahoma City";
ID = 96;
Name = Thunder;
};
date = "2017-04-07";
homeTeam = {
Abbreviation = PHX;
City = Phoenix;
ID = 104;
Name = Suns;
};
location = "Talking Stick Resort Arena";
time = "10:00PM";
};
isCompleted = false;
isInProgress = false;
isUnplayed = true;
quarterSummary = "<null>";
},
{
game = {
ID = 35127;
awayTeam = {
Abbreviation = SAC;
City = Sacramento;
ID = 103;
Name = Kings;
};
date = "2017-04-07";
homeTeam = {
Abbreviation = LAL;
City = "Los Angeles";
ID = 105;
Name = Lakers;
};
location = "Staples Center";
time = "10:30PM";
};
isCompleted = false;
isInProgress = false;
isUnplayed = true;
quarterSummary = "<null>";
}
);
lastUpdatedOn = "<null>";
}]
Here is what I have currently for setting my title and subtitle in Swift:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "NBAScore", for: indexPath)
// Configure the cell...
if let scoreBoard = d.dictionary["scoreboard"] as? [String:AnyObject]
{
if let gameScore = scoreBoard["gameScore"] as? [String:AnyObject]
{
if let game = gameScore["game"] as? [String:AnyObject]
{
if let awayTeam = game["awayTeam"] as? String
{
cell.textLabel?.text = awayTeam }
}
}
}
return cell
}
Best will be to create a Struct add variable's for the properties you need after that make an array from that struct parse your array of json using a for loop and append them to the newly array you have created then you can access those properties using dot notation inside your cellForRow function
Use the below code to get the team name -
if let scoreBoard = d.dictionary["scoreboard"] as? [String:AnyObject]
{
if let gameScore = scoreBoard["gameScore"] as? [String:AnyObject]
{
if let game = gameScore["game"] as? [String:AnyObject]
{
if let awayTeam = game["awayTeam"] as? [String: AnyObject] {
if let teamName = awayTeam["Name"] as? String {
cell.textLabel?.text = teamName
}
}
}
}
}
For that purpose I would use some library that was build to parse JSON dictionaries to some model objects as it's a good practice. E.g. I would recommend Marshal as it's lightweight and easy to use.
You just create a struct or any other Swift structure and then you call Marshal. Later on you use those mapped objects in your tableView dataSource.
Your 'gameScore' object is an array not a dictionary type ([String:AnyObject]). My mistake that i didn't check the json object properly.
First create an array and store all the team name in that array. For Example, I am storing all the awayteam name for now in an array. Check the below code. I didn't run the below source code in my end, Since your json has problem. It's not a valid json data. There is formatting issue. But this below code will work.
let awayTeamArr = NSMutableArray()
if let scoreBoard = d.dictionary["scoreboard"] as? [String:AnyObject] {
if let gameScore = scoreBoard["gameScore"] as? NSArray {
for gameScoreObj in gameScore {
if let gameObj = gameScoreObj as [String: AnyObject] {
if let game = gameObj["game"] as? [String:AnyObject] {
if let awayTeam = game["awayTeam"] as? [String: AnyObject] {
if let teamName = awayTeam["Name"] as? String {
awayTeam.add(teamName)
}
}
}
}
}
}
}
Then in your tableView delegate method for each cell display the object of that specific index of 'awayTeamArr' object. If this answer worked then make the question as completed.
I was able to figure out an answer to my own question. The "gameScore" key of the dictionary was giving me trouble because I was type casting it incorrectly. It was an Array<[String:Any]> not a dictionary.
func parseJSON(){
var s = nbaScore()
var i = 0
if let scoreBoard = d.dictionary["scoreboard"] as? [String:AnyObject]
{
// Could check the lastUpdattedOn date before doing the following:
if let gameScore = scoreBoard["gameScore"] as? Array<[String:Any]>
{ //Loop for # of games
//while gameScore[i]["game"] as? [String:Any] != nil
while i < gameScore.count
//for _ in (gameScore[0]["game"] as? [String:Any])!
{
// An array of dictionaries
if let game = gameScore[i]["game"] as? [String:Any]
{
s.gameTime = (game["time"] as? String)!
if let awayTeam = game["awayTeam"] as? [String:Any]
{
s.awayTeamCity = (awayTeam["City"] as? String)!
s.awayTeamName = (awayTeam["Name"] as? String)!
}
if let homeTeam = game["homeTeam"] as? [String:Any]
{
s.homeTeamCity = (homeTeam["City"] as? String)!
s.homeTeamName = (homeTeam["Name"] as? String)!
}
}
if let isUnplayed = gameScore[i]["isUnplayed"] as? String
{
s.isUnplayed = isUnplayed
}
if let isInProgress = gameScore[i]["isInProgress"] as? String
{
s.isInProgress = isInProgress
}
if let isCompleted = gameScore[i]["isCompleted"] as? String
{
s.isCompleted = isCompleted
}
if let awayScore = gameScore[i]["awayScore"] as? String
{
s.awayTeamScore = awayScore
}
if let homeScore = gameScore[i]["homeScore"] as? String
{
s.homeTeamScore = homeScore
}
i += 1
scores.append(s)
s.clearData()
gamesCount += 1
}
}
}
}

Why can I not access the second level of this array in Swift?

I have the following array which is passed from an API call from a PHP Script:
["playerForm": {
1 = (
{
date = "2017-01-31";
name = Dicky;
result = L;
"results_id" = 42;
},
{
date = "2016-12-24";
name = Dicky;
result = W;
"results_id" = 19;
}
);
2 = (
{
date = "2017-01-25";
name = G;
result = W;
"results_id" = 38;
},
{
date = "2017-01-25";
name = G;
result = D;
"results_id" = 40;
},
{
date = "2017-01-21";
name = G;
result = L;
"results_id" = 34;
}
);
3 = (
{
date = "2017-01-31";
name = Sultan;
result = W;
"results_id" = 42;
},
{
date = "2017-01-15";
name = Sultan;
result = L;
"results_id" = 30;
}
);
}]
However I cannot seem to access the 1,2,3 parts of it...
let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String:AnyObject]
print (json!)
if let dict = json?["playerForm"] as? [String:AnyObject] {
print ("step 1")
if let arr = dict["1"] as? [[String:String]] {
print ("step 2")
self.leagueForm = arr.flatMap { Form($0) }
print (self.leagueForm)
print (self.leagueForm.count)
for i in 0..<self.leagueForm.count {
let form = self.leagueForm[i]
print (form.player_results!)
self.formGuide.append(form.player_results!)
}
print ("now")
print (self.formGuide)
self.resultsDisplay.results = self.formGuide
self.resultsDisplay.results = self.resultsDisplay.results.reversed()
self.resultsDisplay.displayResults()
}
}
With this code above it only gets as far as Step 1.
What am I doing wrong?
UPDATED WITH PROGRSS*
let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String:AnyObject]
print (json!)
if let dict = json?["playerForm"] as? [String:AnyObject] {
print ("step 1")
for (_ , value) in dict {
if let arr = value as? [[String:Any]] {
print(arr)
//your code
}
}
}
Custom Struct to define array:
struct Form {
var player_result: String?
var player_name: String?
var result_date: String?
var result_id: String?
init(_ dictionary: [String : Any]) {
self.player_result = dictionary["result"] as? String ?? ""
self.player_name = dictionary["name"] as? String ?? ""
result_date = dictionary["date"] as? String ?? ""
result_id = String(dictionary["results_id"] as? Int ?? 0)
}
}
Change your array type [[String:String]] to [[String:Any]] because it contains both String and Number as value.
if let arr = dict["1"] as? [[String:Any]] {
print(arr)
//your code
}
Note: You need to loop through the dict Dictionary because its each key having array.
for (_ , value) in dict {
if let arr = value as? [[String:Any]] {
print(arr)
//your code
}
}

NIL when Parsing JSON

I am trying to parse and get the values from this structure of JSON:
["mst_customer": 1, "data": {
0 = 2;
1 = 1;
2 = 1;
3 = "JAYSON TAMAYO";
4 = "581-113-113";
5 = 56;
6 = on;
7 = g;
8 = jayson;
9 = active;
"app_access" = on;
id = 2;
"mst_customer" = 1;
name = "Jayson Tamayo";
status = active;
territory = 1;
}, "status": OK, "staff_id": 2, "staff_name": Jayson Tamayo]
I use the following Swift code to get the values:
(data: Dictionary<String, AnyObject>, error: String?) -> Void in
if error != nil {
print(error)
} else {
if let feed = data["data"] as? NSDictionary ,let entries = data["data"] as? NSArray{
for elem: AnyObject in entries{
if let staff_name = elem["name"] as? String{
print(staff_name)
}
}
}
}
I am trying to get the name by using the keys name or staff_name. But I always get nil.
you want to access staff_name, which is not in "data" variable ... you can simply get that like
if error != nil {
print(error)
} else {
if let name = data["staff_name"] as? String{
print(name)
}
}
for elem: AnyObject in entries{
if let songName = elem["name"] as? String{
print(songName)
}
}
//replace above code with below code
if let songName : String = entries["name"] as? String{
print(songName)
}

How to check value exists in array of dictionary as value?

{
QueueId = 27;
SongId = 38;
artWorkURL = "<null>";
duration = 58258;
"stream_url" = "https://api.soundcloud.com/tracks/233301835/stream";
title = Magenta;
trackID = 233301835;
userAvatar = "https://i1.sndcdn.com/avatars-000188204071-llusgk-large.jpg";
userName = Agiv;
},
{
QueueId = 27;
SongId = 39;
artWorkURL = "<null>";
duration = 79000;
"stream_url" = "https://api.soundcloud.com/tracks/233301833/stream";
title = Nino;
trackID = 233301833;
userAvatar = "https://i1.sndcdn.com/avatars-000157591669-eva3mg-large.jpg";
userName = "SWR Umwelt und Ern\U00e4hrung";
}
My array of dictionary format is as above and multiple tracks i want to check 27 is already there or not ?
You can do this with the filter function
let queueID27Exists = !array.filter({$0["QueueId"] as? Int == 27}).isEmpty
This answer is for your previous JSON object!
if let results : NSDictionary = post.objectForKey("data") as? NSDictionary {
let array:NSArray = (results.valueForKey("track") as! NSArray)
if "25" == array[0].valueForKey("trackID") as? String {
NSLog("YES")
} else {
NSLog("NO")
}
}
var found = false
for (_, data) in post {
let track = data["track"]
if track["trackID"] == "25" {
found = true
}

Resources