Error when decoding JSON - keyNotFound(CodingKeys - json

I am trying to parse JSON data over the network. Below you can see where the magic is happening.
func getBookingsForDate(date: String, completionHandler: #escaping ([String:String]) -> Void ){
struct bookings: Codable {
var bookieName : String
var bookieNumber: String
var booked: String
var bookingTime: String
private enum Codingkeys: String, CodingKey{
case bookieName
case bookieNumber
case booked
case bookingTime
}
}
let params = ["date":date]
let urlString = "http://mscissorss.pythonanywhere.com/getBookings/"
Alamofire.request(urlString, method: .get, parameters: params).responseJSON {
response in
switch response.result {
case .success(let JSON):
let decoder = JSONDecoder()
guard let _ = response.data else{
return
}
do {
let loginDetails = try decoder.decode(bookings.self, from: response.data!)
print(loginDetails)
} catch let err{
print(err)
}
//let bookings = JSON as! NSDictionary
//completionHandler(JSON)
/*
do {
let decoder = JSONDecoder()
let gitData = try decoder.decode(bookings.self, from: JSON)
print(gitData.bookieName)
} catch let err {
print("Err", err)
}
*/
break
case .failure(let error):
print(error)
}
}
}
Given the code i am getting the following error message:
keyNotFound(CodingKeys(stringValue: "bookieName", intValue: nil), Swift.DecodingError.Context(codingPath: [], debugDescription: "No value associated with key CodingKeys(stringValue: \"bookieName\", intValue: nil) (\"bookieName\").", underlyingError: nil))
And the JSON response that i am getting looks like this:
{
0 = {
booked = false;
bookieName = "";
bookieNumber = "";
bookingTime = "10:00";
};
1 = {
booked = false;
bookieName = "";
bookieNumber = "";
bookingTime = "10:30";
};
10 = {
booked = false;
bookieName = "";
bookieNumber = "";
bookingTime = "15:00";
};
11 = {
booked = false;
bookieName = "";
bookieNumber = "";
bookingTime = "15:30";
};
12 = {
booked = false;
bookieName = "";
bookieNumber = "";
bookingTime = "16:00";
};
13 = {
booked = false;
bookieName = "";
bookieNumber = "";
bookingTime = "16:30";
};
14 = {
booked = false;
bookieName = "";
bookieNumber = "";
bookingTime = "17:00";
};
15 = {
booked = false;
bookieName = "";
bookieNumber = "";
bookingTime = "17:30";
};
16 = {
booked = false;
bookieName = "";
bookieNumber = "";
bookingTime = "18:00";
};
2 = {
booked = false;
bookieName = "";
bookieNumber = "";
bookingTime = "11:00";
};
}
It is the first time i am decoding so if you have an answer please try to explain a bit to why i need to make the change that i need.
UPDATE
After changing the code to what #sh_khan and #vadian suggested it worked to parse it however i am still getting this error inside my parsed object:
["1": MagicS.(unknown context at 0x106932738).bookings(bookieName: "", bookieNumber: "", booked: "false", bookingTime: "10:30"),
"0": MagicS.(unknown context at 0x106932738).bookings(bookieName: "", bookieNumber: "", booked: "false", bookingTime: "10:00"),
Also, if i want to be able to access a single value lets say the first item with the key "0" -> bookieName, how would i do that using loginDetails

Firs booked is a Bool and no need for private enum Codingkeys if you won't rename the keys
struct Booking: Codable {
let bookieName : String
let bookieNumber: String
let booked: Bool
let bookingTime: String
}
Second decode like this
let loginDetails = try decoder.decode([String:Booking].self, from: response.data!)

The root object is a dictionary with String keys and Bookings values – please name structs with a starting capital letter.
So you have to decode
let loginDetails = try decoder.decode([String:Bookings].self, from: response.data!)

Related

Swift JSON Data

I received the JSON data as shown below, I want to get the "player_name" & "player_country" from this data. How do I get this?**enter image description here
In case, the image does not load, please refer the below output:
["team_key": 2611, "team_name": Leicester, "team_badge": https://apiv2.apifootball.com/badges/2611_leicester.png, "players": <__NSArrayI 0x600003331e00>(
{
"player_age" = 33;
"player_country" = Denmark;
"player_goals" = 0;
"player_key" = 140150332;
"player_match_played" = 30;
"player_name" = "Schmeichel Kasper";
"player_number" = 1;
"player_red_cards" = 0;
"player_type" = Goalkeepers;
"player_yellow_cards" = 2;
},
{
"player_age" = 23;
"player_country" = England;
"player_goals" = 3;
"player_key" = 2242127097;
"player_match_played" = 24;
"player_name" = "Chilwell Benjamin";
"player_number" = 3;
"player_red_cards" = 0;
"player_type" = Defenders;
"player_yellow_cards" = 2;
},
{.....}
I tried the following to get required data from this:
var mainArray = [[String: Any]]()
var tryArray = [[String]]()
for i in jsonArray {
if i["team_key"] as! String == teamID {
self.mainArray.append(i)
}
}
for i in self.mainArray {
self.tryArray.append(i["player_name"] as! [String])
}
I got this error with the above code:
Fatal error: Unexpectedly found nil while unwrapping an Optional value
let playerArray:NSDictionary = json as! NSDictionary
for var player in playerArray {
self.tryArray.append(player.objectForKey("player_name") as! String)
self.tryArray.append(player.objectForKey("player_country") as! String)
}
Thank you all for your response. I have tried this and it works.
var mainArray = NSArray()
var tryArray = [[String: Any]]()
for i in jsonArray {
if i["team_key"] as! String == teamID {
self.mainArray = i["players"] as! NSArray
}
}
for i in self.mainArray {
tryArray.append(i as! [String : Any])
}
What I did was I made mainArray as NSArray instead of [[String: Any]] and then copy it to tryArray which is of actually [[String: Any]] type and used tryArray for my work.
Thanks.

Array of dictionaries to JSON in Swift

I'm trying to send an array of dictionaries as one of the parameters to an Alamofire request. However, Alamofire is failing on the request.
class PromoCategory {
var promoCategoryId : Int?
var activityId : Int?
var promoCategoryName : String?
var activityName : String!
var statusCd : Int?
init() {
promoCategoryId = 0
promoCategoryName = ""
}
func getDictFormat() -> [String: Any] {
if activityId == nil { activityId = 0 }
if statusCd == nil { statusCd = 0 }
return [
"promoCategoryId" : "\(promoCategoryId!)",
"activityId" : "\(activityId!)",
"promoCategoryName" : promoCategoryName!,
"activityName" : activityName!,
"statusCd" : "\(statusCd!)"
]
}
}
var promoCat = [[String: Any]]()
for cat in promoCategories {
let element = cat.getDictFormat()
promoCat.append(element)
}
var params : [String : Any] = [:]
params["person_id"] = kPersonId
params["person_promo_id"] = promo.personPromoId
params["promo_page_id"] = promo.promoPageId
params["seq_no"] = promo.seqNo
params["promo_type"] = promoTypeString
params["page_name"] = promo.pageName
params["image_name"] = promo.imageName
params["start_date"] = promo.startDate
params["end_date"] = promo.endDate
params["website"] = promo.website
...
params["promoCategories"] = promoCat
Alamofire.request(promoUrl!, method: .post, parameters: params, encoding: JSONEncoding.default, headers: nil)
.validate()
.responseJSON { response in
switch response.result {
case .success(let data):
self.json = JSON(data)
print(self.json as Any)
DispatchQueue.main.async(execute: { () -> Void in
self.dismiss(animated: true, completion: nil)
HUD.hide()
})
case .failure(let error):
self.logApiError(url: (...)
}
}
The error:
Request failed with error:
responseSerializationFailed(Alamofire.AFError.ResponseSerializationFailureReason.jsonSerializationFailed(Error
Domain=NSCocoaErrorDomain Code=3840 "Invalid value around character
0." UserInfo={NSDebugDescription=Invalid value around character 0.}))
If I remove the promoCategories parameter, then it works fine. The params object ends up looking like this:
{
address = "";
bgColorBlue = "0.28936631944444";
bgColorGreen = "0.3072916666666701";
bgColorRed = "0.3063227289789799";
city = "";
"contact_name" = "John Smith";
"contact_phone" = 3065554611;
"country_cd" = CA;
"end_date" = "2017-01-26 21:06:08Z";
"facility_name" = "Conexus Arts Centre";
"image_name" = "EV1.20170126210608302479028.jpg";
latitude = 0;
longitude = 0;
"page_name" = "Test Promo";
"person_id" = 1;
"person_promo_id" = 21;
promoCategories = (
{
activityId = 68;
activityName = "Fashion & Beauty";
promoCategoryId = 271;
promoCategoryName = Accessories;
statusCd = 0;
},
{
activityId = 68;
activityName = "Fashion & Beauty";
promoCategoryId = 273;
promoCategoryName = Beauty;
statusCd = 0;
},
{
activityId = 68;
activityName = "Fashion & Beauty";
promoCategoryId = 270;
promoCategoryName = Fashion;
statusCd = 0;
}
);
"promo_page_id" = 0;
"promo_type" = event;
"prov_state_cd" = "";
"seq_no" = 0;
"start_date" = "2017-01-26 21:06:08Z";
website = "";
}
Is this the approach I should be using? Is there something I have missed? Thanks.

JSON to NSMutableArray stopped working in Swift 2.3 iOS 10

I have a code to consume a REST Service but it stop working after update to swift 2.3 and iOS 10.
I'm getting error in JSON to NSMutableArray Conversion:
class func getStores(latitude:Float, longitude: Float, completion : (Array<Store>?, NSError?) -> ()) {
let latString: String = "\(latitude)"
let lonString: String = "\(longitude)"
var listStores: Array<Store> = []
let urlFull : String = ConstantHelper.baseURLStore
Alamofire.request(.GET, urlFull, parameters: ["latitude":latString, "longitude": lonString])
.responseJSON { response in
switch response.result {
case .Success:
if let repoJSON = response.result.value {
print(repoJSON)
let jsonArray = repoJSON as? NSMutableArray
for item in jsonArray! {
guard let store = Store(json: item as! JSON) else
{
print("Issue deserializing model")
return
}
listStores.append(store)
}
completion(listStores, nil)
}
break
case .Failure(let error):
completion(nil, error)
break
}
}
}
EDIT:
The error is "fatal error: unexpectedly found nil while unwrapping an Optional value"
It means that the variable jsonArray is nil. But its nil only in swift 2.3. Because the conversion json to NSMutableArray don't work more. I need to change the way I convert...but how?
There's the repoJSON value
(
{
cdState = SP;
cdStore = 100;
cdZipCode = "04029200 ";
mnStore = IBI;
noAddress = "AV IBIRAPUERA,";
noAddressAditional = " 3103 - LOJAS 4-5";
noAddressNeighborhood = " 3103";
noCity = "S\U00e3o Paulo ";
noStore = "IBI-M-C-SHOPPING IBIRAPUERA";
vlLatitude = "-23.610113";
vlLongitude = "-46.666505";
},
{
cdState = SP;
cdStore = 105;
cdZipCode = "05724900 ";
mnStore = JSU;
noAddress = "AV GIOVANNI GRONCHI, 5819 - LUC001";
noAddressAditional = "<null>";
noAddressNeighborhood = "VILA ANDRADE";
noCity = "S\U00e3o Paulo ";
noStore = "JSU-C-C-SHOPPING JARDIM SUL";
vlLatitude = "-23.630835";
vlLongitude = "-46.7359";
},
{
cdState = SP;
cdStore = 107;
cdZipCode = "05145000 ";
mnStore = TTE;
noAddress = "AV. RAIMUNDO PEREIRA DE MAGALH\U00c3ES, 1465 \U0096 LOJA \U00c2NCORA 1000";
noAddressAditional = "<null>";
noAddressNeighborhood = "JD \U00cdRIS";
noCity = "S\U00e3o Paulo ";
noStore = "TTE-PP-C-SHOPPING TIET\U00ca PLAZA";
vlLatitude = "-23.506182";
vlLongitude = "-46.718449";
},
{
cdState = SP;
cdStore = 115;
cdZipCode = "03153001 ";
mnStore = CEN;
noAddress = "AV.DR.FRANCISCO MESQUITA, 1000";
noAddressAditional = "<null>";
noAddressNeighborhood = "VILA PRUDENTE";
noCity = "S\U00e3o Paulo ";
noStore = "CEN-PP-C-CENTRAL PLAZA SHOPPING";
vlLatitude = "-23.593389";
vlLongitude = "-46.585574";
}
)
I just updated my code with
let jsonArray = repoJSON as! NSArray
Instead of
let jsonArray = repoJSON as? NSMutableArray
and it works great!

JSON data keep on returning nil

So I have successfully declared some variables obtained by JsonDictionary, but keep on getting nil, here's my code when declaring the variables:
var userName : String!
var text : String!
var name : String!
var tweetID : [NSObject : String]!
var tweetIDStr : String!
var userLocation : String!
var UserImgURLStr : String?
var options : NSJSONReadingOptions!
init(jsonDataDictiony : [String : AnyObject])
{
self.text = jsonDataDictiony["text"] as! String
self.tweetIDStr = jsonDataDictiony["id_str"] as! String
//print(jsonDataDictiony)
if let userDictionary = jsonDataDictiony["user"] as? [String : AnyObject]
{
self.userName = userDictionary["screen_name"] as! String
self.userLocation = userDictionary["location"] as! String
self.name = userDictionary["name"] as! String
}
print(self.text)
print(self.userName)
print(self.userLocation)
print(self.tweetIDStr)
print("-")
}
func castStringToDictionary()
{
let jsonData : NSData = tweetIDStr.dataUsingEncoding(NSUTF8StringEncoding)!
self.tweetID = try! NSJSONSerialization.JSONObjectWithData(jsonData, options: options) as! [NSObject : String]
}
and this is the code when trying to call the function (different class):
var selectedTweet : Tweet!
var twitterNetworkController : NetworkController!
var theTweet = [Tweet]()
override func viewDidLoad()
{
super.viewDidLoad()
self.navigationItem.title = selectedTweet.name + "'s tweet"
twitterNetworkController.fetchTweetID(selectedTweet.tweetID!)
//it gets a nil value here ^
{
(results, error) in
if error == nil
{
self.theTweet = results!
self.selectedFeedTableView.reloadData()
}
else
{
print(error)
}
}
}
Here's the console print:
["in_reply_to_user_id": , "possibly_sensitive_appealable": 0, "favorite_count": 0, "possibly_sensitive": 0, "in_reply_to_status_id": , "in_reply_to_user_id_str": , "lang": en, "favorited": 0, "id": 736420019152637952, "text": 🐐 (at Sate Tegal Marem) — url, "coordinates": , "geo": , "user": {
"contributors_enabled" = 0;
"created_at" = "Mon May 21 09:06:46 +0000 2012";
"default_profile" = 0;
"default_profile_image" = 0;
description = "\Uad1c\Ucc2e\Uc744\Ud150\Ub370 \U2b50";
entities = {
description = {
urls = (
);
};
};
"favourites_count" = 11;
"follow_request_sent" = 0;
"followers_count" = 155;
following = 1;
"friends_count" = 134;
"geo_enabled" = 0;
"has_extended_profile" = 0;
id = 586390966;
"id_str" = 586390966;
"is_translation_enabled" = 0;
"is_translator" = 0;
lang = en;
"listed_count" = 0;
location = "";
name = "tania.";
notifications = 0;
"profile_background_color" = B4DEBA;
"profile_background_image_url" = img url;
"profile_background_image_url_https" = img url;
"profile_background_tile" = 0;
"profile_banner_url" = banner url = img url;
"profile_image_url_https" = img url;
"profile_link_color" = 44A681;
"profile_sidebar_border_color" = FFFFFF;
"profile_sidebar_fill_color" = FFFFFF;
"profile_text_color" = 333333;
"profile_use_background_image" = 1;
protected = 0;
"screen_name" = "tania_alice";
"statuses_count" = 2332;
"time_zone" = Jakarta;
url = "";
"utc_offset" = 25200;
verified = 0;
}, "id_str": 736420019152637952, "created_at": Sat May 28 04:53:09 +0000 2016,
I replaced all the urls since it gave error (my reputation is less than 10 and I cannot post urls)

Error passing data from JSON Swift into a array

I get a error: "fatal error: unexpectedly found nil while unwrapping an Optional value" when I try to pass the result of the JSON into an array. I think that the problem is when I try to get the geo coordinate: lat and long into my variables.
Please can somebody help me with this issue?
The code for the passing de result of the JSON to an array is:
ViewController.swift
import UIKit
import MapKit
import Alamofire
class ViewController: UIViewController {
var artworks = [Artwork]()
#IBOutlet weak var mapView: MKMapView!
let initialLocation = CLLocation(latitude: 52.370216, longitude: 4.895168)
let regionRadius: CLLocationDistance = 6000
override func viewDidLoad() {
super.viewDidLoad()
centerMapOnLocation(initialLocation)
getData()
mapView.addAnnotations(artworks)
mapView.delegate = self
}
func getData() {
Alamofire.request(.GET , "http://kaart.amsterdam.nl/datasets/datasets-item/t/kunstwerken-in-de-openbare-ruimte/export/json").responseJSON() {
(_, _, json, _) in
println(json)
var json = JSON(json!)
if let appArray = json["features"].array {
for artObject in appArray {
let title = artObject["properties"]["titel"].string
let locationName = artObject["properties"]["titel_key"].string
let discipline = artObject["properties"]["titel_key"].string
let latitude = (artObject["geometry"]["coordinates"].string! as NSString).doubleValue
let longitude = (artObject["geometry"]["coordinates"].string! as NSString).doubleValue
let coordinate = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
var openArt1 = Artwork(title: title!, locationName: locationName!, discipline: discipline!, coordinate: coordinate)
self.artworks.append(openArt1)
self.mapView.addAnnotations(self.artworks)
}
}
}
}
func centerMapOnLocation(location: CLLocation) {
let coordinateRegion = MKCoordinateRegionMakeWithDistance(location.coordinate, regionRadius * 2.0, regionRadius * 2.0)
mapView.setRegion(coordinateRegion, animated: true)
}
the result of the JSON looks like this:
Optional({
features = (
{
geometry = {
coordinates = (
"4.9305202013246",
"52.363277804149"
);
type = Point;
};
properties = {
adres = "";
content = "";
"content_src" = "";
"date_created" = "2015-05-16 00:07:58";
"date_modified" = "<null>";
datum = "2013-10-09 17:15:00";
email = "";
"id_2" = "";
"link_href" = "";
locatie = "POINT(4.93052020132461 52.363277804148602)";
omschrijving = "";
plaats = "";
postcode = "";
published = "";
summary = "";
"summary_type" = "";
telefoonnummer = "";
titel = "101 namen - 136602";
"titel_key" = "101_namen_136602";
title = "";
type = Kunstwerk;
updated = "";
website = "http://www.amsterdam.nl/kunstencultuur/kunst-openbare/kunst-openbare/kunstwerken/amsterdam-stadsdeel-0/dapperbuurt/101-namen-136602/";
};
artObject["geometry"]["coordinates"] is an Array of Doubles, not a String.
If you println the JSON response it could be confusing as you see the Doubles wrapped into quotes (") but it is an array of Doubles nonetheless in the JSON for the "coordinates" key.
UPDATE:
I just checked and they are Doubles:
var err: NSError?
let data = NSData(contentsOfURL: NSURL(string: "http://kaart.amsterdam.nl/datasets/datasets-item/t/kunstwerken-in-de-openbare-ruimte/export/json")!)
let json = NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.allZeros, error: &err) as! [String:AnyObject]
let features = json["features"] as! [[String:AnyObject]]
let object1 = features[0]
let geo = object1["geometry"]?["coordinates"] as! [Double]
let lat = geo[0] // 4.9305202013246
let lon = geo[1] // 52.363277804149
You just have to access these values with SwiftyJSON like this in your loop:
let coo = artObject["geometry"]["coordinates"].array!
let latitude = coo[0].doubleValue
let longitude = coo[1].doubleValue