Swift: key not found JSON decoding - json

I am trying to decode a JSON object, from this website: https://www.thesportsdb.com/api/v1/json/1/search_all_leagues.php?c=France&s=Soccer
I would like to store them in an array of Soccer elements, and show them in cells.
This is the code I did, but I have key not found errors, how is that possible?
class Soccer: Codable {
var strLeague: String
var strDescriptionEN: String
var strBadge: String
var strDivision: String
var intFormedYear: String
var strCountry: String
init(strLeague: String, strDescriptionEN: String, strBadge: String, strDivision: String, intFormedYear: String, strCountry: String) {
self.strLeague = strLeague
self.strDescriptionEN = strDescriptionEN
self.strBadge = strBadge
self.strDivision = strDivision
self.intFormedYear = intFormedYear
self.strCountry = strCountry
}
}
class SoccerTVC: UITableViewController {
var leagues = [Soccer]()
func download(at url: String, handler: #escaping (Data?) -> Void)
{
// 1 - Create URL
guard let url = URL(string: url) else {
debugPrint("Failed to create URL")
handler(nil)
return
}
// 2 - Create GET Request
var request: URLRequest = URLRequest(url: url)
request.httpMethod = "GET"
// 3 - Create download task, handler will be called when request ended
let task = URLSession.shared.dataTask(with: request) {
(data, response, error) in handler(data)
}
task.resume()
}
func getSoccer() {
// 1 - Download Soccer
download(at: "https://www.thesportsdb.com/api/v1/json/1/search_all_leagues.php?c=France&s=Soccer")
{ (SoccerData) in
if let Soccerdata = SoccerData {
// 2 - Decode JSON into a array of Game object
let decoder: JSONDecoder = JSONDecoder()
do {
let jsonData = [try decoder.decode(Soccer.self, from: Soccerdata)]
self.leagues = jsonData
debugPrint(self.leagues)
DispatchQueue.main.sync {
self.tableView.reloadData()
}
}
catch {
debugPrint("Failed to parse data - error: \(error)")
}
}
else
{
debugPrint("Failed to get soccer data")
}
}
}
override func viewDidLoad() {
getSoccer()
super.viewDidLoad()
}
}
Error message:
Failed to parse data - error: keyNotFound(CodingKeys(stringValue:
"strLeague", intValue: nil), Swift.DecodingError.Context(codingPath:
[], debugDescription: "No value associated with key
CodingKeys(stringValue: \"strLeague\", intValue: nil)
(\"strLeague\").", underlyingError: nil))

Your desired values is in country array key so you need to change your struct with :
struct Soccer: Codable {
let countrys : [Country]?
}
struct Country : Codable{
var strLeague: String
var strDescriptionEN: String
var strBadge: String
....
}
And you need to change your json decoder like :
var leagues = [Country]()
let jsonData = try decoder.decode(Soccer.self, from: Soccerdata)
self.leagues = jsonData.countrys
}

Try this instead:
let jsonData = try JSONDecoder().decode([String:[Soccer]].self, from: Soccerdata)
self.leagues = jsonData.values

Related

SwiftUI decoding JSON from API

I know there are already some articles regarding this issue, but I could not find anything related to my JSON.
This is how my JSON likes like:
{
"message": {
"affenpinscher": [],
"african": [],
"airedale": [],
"akita": [],
"appenzeller": [],
"australian": [
"shepherd"
],
"basenji": []
},
"status: "succes"
}
So, if I understand it correctly it is dictionary because it starts with {, but what are the things inside the "message"?
This is my Dog.swift class where I am re-writing the JSON, but I am not sure if it is correct:
class Dog: Decodable, Identifiable {
var message: Message?
var status: String?
}
struct Message: Decodable {
var affenpinscher: [String:[String]]?
var african: [String]?
var airedale: [String]?
var akita: [String]?
var appenzeller: [String]?
var australian: [String]?
var basenji: [String]?
}
As you can see in the first value I was trying to play with data types, but no success.
I am decoding and parsing JSON here:
class ContentModel: ObservableObject {
#Published var dogs = Message()
init() {
getDogs()
}
func getDogs(){
// Create URL
let urlString = Constants.apiUrl
let url = URL(string: urlString)
if let url = url {
// Create URL request
var request = URLRequest(url: url, cachePolicy: .reloadIgnoringLocalCacheData, timeoutInterval: 10)
request.httpMethod = "GET"
// Get URLSession
let session = URLSession.shared
// Create Data Task
let dataTask = session.dataTask(with: request) { (data, response, error) in
// Check that there is not an error
if error == nil {
do {
// Parse JSON
let decoder = JSONDecoder()
let result = try decoder.decode(Dog.self, from: data!)
print(result)
// Assign result to the dogs property
DispatchQueue.main.async {
self.dogs = result.message!
}
} catch {
print(error)
}
}
}
// Start the Data Task
dataTask.resume()
}
}
}
And here I would love to iterate through it eventually, which I also have no idea how to do it:
struct ContentView: View {
#EnvironmentObject var model: ContentModel
var body: some View {
NavigationView {
ScrollView {
LazyVStack {
if model.dogs != nil {
// ForEach(Array(model.dogs.keys), id: \.self) { d in
// Text(d)
// }
}
}
.navigationTitle("All Dogs")
}
}
}
}
What can I try next to resolve this?
First of all don't use classes for a JSON model and to conform to Identifiable you have to add an id property and CodingKeys if there is no key id in the JSON.
My suggestion is to map the unhandy [String: [String]] dictionary to an array of an extra struct
I renamed Dog as Response and named the extra struct Dog
struct Dog {
let name : String
let types : [String]
}
struct Response: Decodable, Identifiable {
private enum CodingKeys: String, CodingKey { case message, status }
let id = UUID()
let dogs: [Dog]
let status: String
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
status = try container.decode(String.self, forKey: .status)
let message = try container.decode([String:[String]].self, forKey: .message)
dogs = message.map(Dog.init).sorted{$0.name < $1.name}
}
}
In the model declare
#Published var dogs = [Dog]()
and decode
let result = try decoder.decode(Response.self, from: data!)
print(result)
// Assign result to the dogs property
DispatchQueue.main.async {
self.dogs = result.dogs
}
The dogs array can be displayed seamlessly in a List
PS: Actually appenzeller is supposed to be
"appenzeller": ["sennenhund"],
or correctly in English
"appenzell": ["mountain dog"],
😉😉😉
Using the native Swift approach that #vadian answered is a much lighter weight solution, but if you work with JSON often I'd recommend using SwiftyJSON.
You can parse the URL data task response into a Swifty json object like so:
import SwiftyJSON
guard let data = data, let json = try? JSON(data: data) else {
return
}
// Make sure the json fetch was successful
if json["status"].stringValue != "success" {
return
}
Then you can access the message object safely without the verbosity of using Decodable. Here the message is parsed into an array of dog structs:
struct Dog {
let name : String
let types : [String]
}
var dogs: [Dog] = []
/// Load the docs into an array
for (name, typesJson) in json["message"].dictionaryValue {
dogs.append(Dog(name: name, types: typesJson.arrayValue.map { $0.stringValue }))
}
print("dogs", dogs)

Fetching Data from API in Swift

So I am trying to fetch data from the Pokemon API, and I am getting stuck at the point where I am trying to decode the JSON into a struct. Here is my code:
{
"count":1118,
"next":"https://pokeapi.co/api/v2/pokemon/?offset=20&limit=20",
"previous":null,
"results":
[
{"name":"bulbasaur","url":"https://pokeapi.co/api/v2/pokemon/1/"},
{"name":"ivysaur","url":"https://pokeapi.co/api/v2/pokemon/2/"},
{"name":"venusaur","url":"https://pokeapi.co/api/v2/pokemon/3/"},
{"name":"charmander","url":"https://pokeapi.co/api/v2/pokemon/4/"},
{"name":"charmeleon","url":"https://pokeapi.co/api/v2/pokemon/5/"},
{"name":"charizard","url":"https://pokeapi.co/api/v2/pokemon/6/"},
{"name":"squirtle","url":"https://pokeapi.co/api/v2/pokemon/7/"},
{"name":"wartortle","url":"https://pokeapi.co/api/v2/pokemon/8/"},
{"name":"blastoise","url":"https://pokeapi.co/api/v2/pokemon/9/"},
{"name":"caterpie","url":"https://pokeapi.co/api/v2/pokemon/10/"},
{"name":"metapod","url":"https://pokeapi.co/api/v2/pokemon/11/"},
{"name":"butterfree","url":"https://pokeapi.co/api/v2/pokemon/12/"},
{"name":"weedle","url":"https://pokeapi.co/api/v2/pokemon/13/"},
{"name":"kakuna","url":"https://pokeapi.co/api/v2/pokemon/14/"},
{"name":"beedrill","url":"https://pokeapi.co/api/v2/pokemon/15/"},
{"name":"pidgey","url":"https://pokeapi.co/api/v2/pokemon/16/"},
{"name":"pidgeotto","url":"https://pokeapi.co/api/v2/pokemon/17/"},
{"name":"pidgeot","url":"https://pokeapi.co/api/v2/pokemon/18/"},
{"name":"rattata","url":"https://pokeapi.co/api/v2/pokemon/19/"},
{"name":"raticate","url":"https://pokeapi.co/api/v2/pokemon/20/"}
]
}
func fetchPokemon() {
let defaultSession = URLSession(configuration: .default)
if let url = URL(string: "https://pokeapi.co/api/v2/pokemon/") {
let request = URLRequest(url:url)
let dataTask = defaultSession.dataTask(with: request, completionHandler: { (data, response, error) -> Void in
guard error == nil else {
print ("error: ", error!)
return
}
guard data != nil else {
print("No data object")
return
}
guard let httpResponse = response as? HTTPURLResponse, (200...299).contains(httpResponse.statusCode) else {
print("response is: ", response!)
return
}
guard let mime = response?.mimeType, mime == "application/json" else {
print("Wrong MIME type!")
return
}
DispatchQueue.main.async {
guard let result = try? JSONDecoder().decode(PokemonList.self, from: data!) else {
print("Error Parsing JSON")
return
}
let pokemon = result.pokemon
self.Pokemon = pokemon
print(self.Pokemon)
}
})
dataTask.resume()
}
}
and here is the pokemon struct:
struct Pokemon {
// Various properties of a post that we either need or want to display
let name: String
let url: String
}
extension Pokemon: Decodable {
// properties within a Post returned from the Product Hunt API that we want to extract the info from.
enum PokemonKeys: String, CodingKey {
// first three match our variable names for our Post struct
case name = "name"
case url = "url"
}
init(from decoder: Decoder) throws {
let postsContainer = try decoder.container(keyedBy: PokemonKeys.self)
name = try postsContainer.decode(String.self, forKey: .name)
url = try postsContainer.decode(String.self, forKey: .url)
}
}
struct PokemonList: Decodable {
var pokemon: [Pokemon]
}
It keeps reaching the point when decoding which says "Error Parsing JSON". I'm assuming that there may be an error in how I setup the pokemon struct?
Any ideas?
you are getting a parse error because the data model is not the same. your struct should be:
struct PokemonList: Decodable {
var results: [Pokemon]
var count: Int
var next: String
}
you don't need the extension.

How to Parse JSON data from a URL and append to a UiLabel with Swift 5

I am trying to get data from Json url for this specific line "ConfirmedCount" from https://raw.githubusercontent.com/BlankerL/DXY-COVID-19-Data/master/json/DXYOverall.json to a UiLabel that I created but keeps getting error. I have been trying to do this for week now.
Here is my code:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var labeltest: UILabel!
//the json file url
let URL_HEROES = "https://raw.githubusercontent.com/BlankerL/DXY-COVID-19-Data/master/json/DXYOverall.json";
//the label we create
#IBOutlet weak var labelTest: UILabel!
//A string array to save all the names
var nameArray = [String]()
override func viewDidLoad() {
super.viewDidLoad()
//calling the function that will fetch the json
getJsonFromUrl()
}
//this function is fetching the json from URL
func getJsonFromUrl(){
//creating a NSURL
let url = NSURL(string: URL_HEROES)
//fetching the data from the url
URLSession.shared.dataTask(with: (url as URL?)!, completionHandler: {(data, response, error) -> Void in
if let jsonObj = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? NSDictionary {
//printing the json in console
print(jsonObj.value(forKey: "results")!)
//getting the avengers tag array from json and converting it to NSArray
if let heroeArray = jsonObj.value(forKey: "results") as? NSArray {
//looping through all the elements
for results in heroeArray{
//converting the element to a dictionary
if let heroeDict = results as? NSDictionary {
var confirmedCount: Int
//getting the name from the dictionary
if let confirmedCount = heroeDict.value(forKey: "confirmedCount") {
//adding the name to the array
self.nameArray.append((String (format: "1234", confirmedCount as! Int)))
}
}
}
}
OperationQueue.main.addOperation({
//calling another function after fetching the json
//it will show the names to label
self.showNames()
})
}
}).resume()
}
func showNames(){
//looping through all the elements of the array
for confirmedCount in nameArray{
labelTest.text = (confirmedCount)
}
}
}
This is the error that I am getting:
(
{
abroadRemark = "";
confirmedCount = 80422;
confirmedIncr = 120;
curedCount = 49923;
curedIncr = 2663;
currentConfirmedCount = 27515;
currentConfirmedIncr = "-2581";
deadCount = 2984;
deadIncr = 38;
generalRemark = "\U7591\U4f3c\U75c5\U4f8b\U6570\U6765\U81ea\U56fd\U5bb6\U536b\U5065\U59d4\U6570\U636e\Uff0c\U76ee\U524d\U4e3a\U5168\U56fd\U6570\U636e\Uff0c\U672a\U5206\U7701\U5e02\U81ea\U6cbb\U533a\U7b49";
note1 = "\U75c5\U6bd2\Uff1aSARS-CoV-2\Uff0c\U5176\U5bfc\U81f4\U75be\U75c5\U547d\U540d COVID-19";
note2 = "\U4f20\U67d3\U6e90\Uff1a\U65b0\U51a0\U80ba\U708e\U7684\U60a3\U8005\U3002\U65e0\U75c7\U72b6\U611f\U67d3\U8005\U4e5f\U53ef\U80fd\U6210\U4e3a\U4f20\U67d3\U6e90\U3002";
note3 = "\U4f20\U64ad\U9014\U5f84\Uff1a\U7ecf\U547c\U5438\U9053\U98de\U6cab\U3001\U63a5\U89e6\U4f20\U64ad\U662f\U4e3b\U8981\U7684\U4f20\U64ad\U9014\U5f84\U3002\U6c14\U6eb6\U80f6\U4f20\U64ad\U548c\U6d88\U5316\U9053\U7b49\U4f20\U64ad\U9014\U5f84\U5c1a\U5f85\U660e\U786e\U3002";
remark1 = "\U6613\U611f\U4eba\U7fa4\Uff1a\U4eba\U7fa4\U666e\U904d\U6613\U611f\U3002\U8001\U5e74\U4eba\U53ca\U6709\U57fa\U7840\U75be\U75c5\U8005\U611f\U67d3\U540e\U75c5\U60c5\U8f83\U91cd\Uff0c\U513f\U7ae5\U53ca\U5a74\U5e7c\U513f\U4e5f\U6709\U53d1\U75c5";
remark2 = "\U6f5c\U4f0f\U671f\Uff1a\U4e00\U822c\U4e3a 3\Uff5e7 \U5929\Uff0c\U6700\U957f\U4e0d\U8d85\U8fc7 14 \U5929\Uff0c\U6f5c\U4f0f\U671f\U5185\U53ef\U80fd\U5b58\U5728\U4f20\U67d3\U6027\Uff0c\U5176\U4e2d\U65e0\U75c7\U72b6\U75c5\U4f8b\U4f20\U67d3\U6027\U975e\U5e38\U7f55\U89c1";
remark3 = "\U5bbf\U4e3b\Uff1a\U91ce\U751f\U52a8\U7269\Uff0c\U53ef\U80fd\U4e3a\U4e2d\U534e\U83ca\U5934\U8760";
remark4 = "";
remark5 = "";
seriousCount = 6416;
seriousIncr = "-390";
suspectedCount = 520;
suspectedIncr = 143;
updateTime = 1583295001876;
}
)
Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value: file /Users/AbdalQaydi/Desktop/jnews/jnews/ViewController.swift, line 84
2020-03-04 00:26:49.829895-0500 jnews[12702:1192396] Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value: file /Users/AbdalQaydi/Desktop/jnews/jnews/ViewController.swift, line 84
(lldb)
It looks like it can parse the data but I don't know how to add the json data for line "confirmedCount" to label.
Please any help is really appreciated. I have been trying to figure out how to do this and just can't find a way.
Use Codable to parse the JSON data.
Models:
struct Root: Decodable {
let results: [Result]
let success: Bool
}
struct Result: Decodable {
let currentConfirmedCount, confirmedCount, suspectedCount, curedCount: Int
let deadCount, seriousCount, currentConfirmedIncr, confirmedIncr: Int
let suspectedIncr, curedIncr, deadIncr, seriousIncr: Int
let generalRemark, abroadRemark, remark1, remark2: String
let remark3, remark4, remark5, note1: String
let note2, note3: String
let updateTime: Int
}
Parse the data like,
if let url = URL(string: URL_HEROES) {
URLSession.shared.dataTask(with: url) { (data, response, error) in
if let data = data {
do {
let response = try JSONDecoder().decode(Root.self, from: data)
let confirmedCountArr = response.results.map { String($0.confirmedCount) }
nameArray.append(contentsOf: confirmedCountArr)
//rest of the code...
} catch {
print(error)
}
}
}.resume()
}

Parsing JSON array without for statement

I want to find a solution for parsing JSON array. there is my code for parsing JSON but I want a solution without for statement I can parse array.
code for parsing:
func parsigJsonData(resultArray:any?){
if let resultArray = resultDic["trucks"] as? BaseModelData {
print(resultArray)
}
}
class BaseModel {
public typealias BaseModelData = (id:String?,title:String?,select:Bool)
var id : String?
var title : String?
var select : Bool = false
init(json: [String:Any]) {
self.id = json["id"] as? String
self.title = json["title"] as? String
self.select = false
}
}
extension BaseModel {
var tableRepresentation: [BaseModelData] {
return [(id:id,title:title,select:select)]
}
}
result array contains list of baseModel object. I try this code for parsing but that's not working and casting to BaseModelData unsuccessful.
if there is a solution for parsing JSON array without for statement?
Thank you for the solutions.
there is my json response sample:
{"trucks":[{"id":"1","title":"\u062e\u0627\u0648\u0631 \u062a\u0627 5 \u062a\u0646 \u0627\u062a\u0627\u0642 \u0686\u0648\u0628\u06cc"},{"id":"2","title":"\u062e\u0627\u0648\u0631 \u062a\u0627 5 \u062a\u0646 \u06a9\u0645\u067e\u0631\u0633\u06cc"},{"id":"3","title":"\u062e\u0627\u0648\u0631 \u062a\u0627 8 \u062a\u0646 \u0627\u062a\u0627\u0642 \u0686\u0648\u0628\u06cc"},{"id":"4","title":"\u062e\u0627\u0648\u0631 \u062a\u0627 8 \u062a\u0646 \u06a9\u0645\u067e\u0631\u0633\u06cc"},{"id":"5","title":"\u062e\u0627\u0648\u0631 \u06cc\u062e\u0686\u0627\u0644 \u062f\u0627\u0631"}]
Swift 4 allows you to make it very simple. Just add Decodable protocol,
struct BaseModel: Codable {
var id : String?
var title : String?
var select : Bool = false
}
And use this to retrieve data:
func makeRequest(completionHandler: #escaping ([BaseModel]?, Error?) -> Void) {
var urlRequest = URLRequest(url: url)
request.httpMethod = "GET"
let task = URLSession.shared.dataTask(with: request as URLRequest){
(data, response, error) in
guard let responseData = data else {
print("Error: did not receive data")
completionHandler(nil, error)
return
}
guard error == nil else {
completionHandler(nil, error)
return
}
let decoder = JSONDecoder()
do {
let dataObject = try decoder.decode([BaseModel].self, from: responseData)
completionHandler(dataObject, nil)
} catch {
print("error trying to convert data to JSON")
print(error)
completionHandler(nil, error)
}
}
task.resume()
}

Convert a callback Swift JSON AnyObject into a NSDictionary

I have a network connection with reads the data using JSON and gives a callback;
executeRequestURL(requestURL: url, taskCallback: {(status, resp) -> Void in
if (status == true) {
if let results = resp as? NSDictionary {
print ("\(results.count) results found")
let list = results.allValues.first as! NSArray
print (list)
}
} else {
print ("Error -- \(resp)")
}
})
This calls;
private class func executeRequestURL(requestURL: NSURL, taskCallback: #escaping (Bool, AnyObject?) -> ()) {
print ("Attempting URL -- \(requestURL)")
let request: NSURLRequest = NSURLRequest(url: requestURL as URL, cachePolicy: .reloadIgnoringLocalAndRemoteCacheData, timeoutInterval: kAPI_TIMEOUT)
let session: URLSession = URLSession.shared
let task = session.dataTask(with: request as URLRequest, completionHandler: {
(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)
if let response = response as? HTTPURLResponse , 200...299 ~= response.statusCode {
taskCallback(true, json as AnyObject?)
} else {
taskCallback(false, json as AnyObject?)
}
})
task.resume()
}
The problem I have is that I want to read the results into a dictionary, loop through it and create objects.
For now, I will put my code in the executeRequestURL just to ensure it works, but I intend to seperate this code away for the required entity.
Question:
How do I read the resp as a dictionary?
Thanks
Sample response follows;
{
"objects": [
{
"uid": "coll_20ce39424470457c925f823fc150b3d4",
"title": "Popular",
"temp_image": "",
"body": "",
"active": true,
"slug": "popular",
"created": "2014-10-25T12:45:54+00:00",
"modified": "2014-10-25T12:45:54.159000+00:00",
"ends_on": "2100-01-01T00:00:00+00:00",
}
]
}
As the JSON is a dictionary, return a dictionary ([String:Any]) from the callback. In Swift 3 AnyObject has become Any. The strong type system of Swift encourages to be always as specific as possible.
Do a better error handling! You should return an error rather than just false.
The code uses the new Swift 3 structs URL and URLRequest
private class func executeRequestURL(requestURL: URL, taskCallback: #escaping (Bool, [String:Any]?) -> ()) {
print ("Attempting URL -- \(requestURL)")
let request = URLRequest(url: requestURL, cachePolicy: .reloadIgnoringLocalAndRemoteCacheData, timeoutInterval: kAPI_TIMEOUT)
let session = URLSession.shared
let task = session.dataTask(with: request, completionHandler: {
(data, response, error) in
guard error == nil else {
print(error)
taskCallback(false, nil)
return
}
guard let data = data else {
print("Data is empty") // <- this will never be reached. If there is no error,
taskCallback(false, nil) // data is always non-nil.
return
}
if let response = response as? HTTPURLResponse , 200...299 ~= response.statusCode {
let json = try! JSONSerialization.jsonObject(with: data, options: []) as! [String:Any]
taskCallback(true, json)
} else {
taskCallback(false, nil)
}
})
task.resume()
}
The JSON result contains a dictionary with one key objects which contains an array of dictionaries. JSON collection types are very easy to distinguish: {} is dictionary, [] is array.
To map the JSON to objects create a struct
struct Item {
var uid : String
var title : String
var tempImage : String
var body : String
var active : Bool
var slug : String
var created : String
var modified : String
var endOn : String
}
and an array
var items = [Item]()
Then map the dictionaries to Item
if let objects = json["objects"] as? [[String:Any]] {
for object in objects {
let uid = object["uid"] as! String
var title = object["title"] as! String
var tempImage = object["temp_image"] as! String
var body = object["body"] as! String
var active = object["active"] as! Bool
var slug = object["slug"] as! String
var created = object["created"] as! String
var modified = object["modified"] as! String
var endOn = object["end_on"] as! String
let item = Item(uid: uid, title: title, tempImage:tempImage, body: body, active: active, slug: slug, created: created, modified: modified, endOn: endOn)
items.append(item)
}
The JSON values seem to come from a database which includes always all fields so the forced unwrapped values are safe.
I've done it like so:
func getHttpData(urlAddress : String)
{
// Asynchronous Http call to your api url, using NSURLSession:
guard let url = URL(string: urlAddress) else
{
print("Url conversion issue.")
return
}
URLSession.shared.dataTask(with: url, completionHandler: { (data, response, error) -> Void in
// Check if data was received successfully
if error == nil && data != nil {
do {
// Convert NSData to Dictionary where keys are of type String, and values are of any type
let json = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers) as! [String:AnyObject]
// Call whatever function you want to do with your dictionary
useMyDictionary(dictionary: json)
} catch {
print(error)
// Something went wrong
}
}
else if error != nil
{
print(error)
}
}).resume()
}
There are many other ways but I like to do it using ObjectMapper. it looks cleaner to me. So just create a new Swift file, import ObjectMapper and write below code.
class yourDataModel: Mappable {
// MARK: - Constants & Variables
var myObjects: [yourDataModel]
required init?(_ map: Map) {
myObjects = []
}
func mapping(map: Map) {
myObjects <- map["objects"]
}
}
class YourCustomObjects: Mappable {
// MARK: - Constants & Variables
var userId:String
var title:String
var tempimage:String
var body:String
var active:Bool
var slug : String
var createdDate:String
var modifiedDate:String
var endDate:String
// MARK: - init
required init?(_ map: Map) {
userId = ""
title = ""
tempimage = ""
body = ""
active = false
slug = ""
createdDate = ""
modifiedDate = ""
endDate = ""
}
func mapping(map: Map) {
userId <- map["uid"]
title <- map["title"]
tempimage <- map["temp_image"]
body <- map["body"]
active <- map["active"]
slug <- map["slug"]
createdDate <- map["created"]
modifiedDate <- map["modified"]
endDate <- map["ends_on"]
}
}
Basically its your model class, now you just have to pass it your result in JSON which will be an AnyObject hopefully, and it will give you an array containing all your "objects" in it. You can use it like below
if let data = Mapper<yourDataModel>().map(resp){
print(data)
}
Try this, and let me know if you face any difficulty.