how to parse the children array using json in swift 3? - ios

In this i need to get the elements from children array which will be in below mentioned url and i need to get the children array from all 11 objects can anyone help me how to implement this ?
let url = "http://www.json-generator.com/api/json/get/cwqUAMjKGa?indent=2"
var detailsArray :[[String: AnyObject]] = []
var productName = [String]()
var childrenArray :[[String: AnyObject]] = []
override func viewDidLoad() {
super.viewDidLoad()
downloadJsonWithURL()
// Do any additional setup after loading the view.
}
func downloadJsonWithURL() {
let url = NSURL(string: self.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 {
self.detailsArray = (jsonObj!.value(forKey: "data") as? [[String: AnyObject]])!
print(self.detailsArray)
for item in self.detailsArray{
if let detailDict = item as? NSDictionary {
if let name = detailDict.value(forKey: "name"){
self.productName.append(name as! String)
}
}
}
OperationQueue.main.addOperation({
print(self.productName)
print(self.childrenArray)
})
}
}).resume()
}

iterate the detailsArray and for key "children" append the data to childrenArray
for item in self.detailsArray {
if let detailDict = item as? [String: Any] {
if let child = detailDict["children"] {
self. childrenArray.append(child)
}
}
}

Try out this :
func downloadJsonWithURL() {
let url = NSURL(string: self.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 {
self.detailsArray = (jsonObj!.value(forKey: "data") as? [[String: AnyObject]])!
print(self.detailsArray)
for item in self.detailsArray{
if let detailDict = item as? [String:Any] {
if let name = detailDict["name"] as? String {
self.productName.append(name as! String)
}
if let children = detailDict["children
"] as? [Any] {
self.childrenArray.append(children)
}
}
}
OperationQueue.main.addOperation({
print(self.productName)
print(self.childrenArray)
})
}
}).resume()
}

Related

Why URLSession.DataTask.shared is not working properly?

I need to fetch some quizzes for my application from the server. Unfortunately, it seems that URLSession.DataTask.shared is not working. How do I fix the problem?
This is for Swift 4.
import Foundation
import UIKit
class QuizService {
let baseUrl = "https://iosquiz.herokuapp.com/api/quizzes"
func fetchQuizzes(completion: #escaping (([Quiz]?) -> Void)) -> Void {
if let url = URL(string: baseUrl) {
let request = URLRequest(url: url)
let dataTask = URLSession.shared.dataTask(with: request) { (data, response, error) in
if let data = data {
do {
let json = try JSONSerialization.jsonObject(with: data, options: [])
if let resultsList = json as? [String: Any], let results = resultsList["quizzes"] as? [[String: Any]] {
let quizzes = results.map({ json -> Quiz? in
print(json)
if
let title = json["title"] as? String,
let id = json["id"] as? Int,
let level = json["level"] as? Int,
let description = json["description"] as? String,
let category = json["category"] as? String,
let questions = json["questions"] as? [String: Any],
let imageUrl = json["image"] as? String {
let quiz=Quiz(id:id,title:title,descript:description,category:category,level:level,imageUrl:imageUrl,questions:questions)
return quiz
} else {
return nil
}
}).filter { $0 != nil } .map { $0! }
completion(quizzes)
} else {
completion(nil)
}
} catch {
completion(nil)
}
} else {
completion(nil)
}
}
dataTask.resume()
} else {
completion(nil)
}
}
}
My error is that field of quizzes are null, so my code is not working in my view controller.
I took a look at the response here https://iosquiz.herokuapp.com/api/quizzes.
The "questions" should be array of dictionaries instead of dictionary.
so it should works if you replace this line
let questions = json["questions"] as? [String: Any]
with this line
let questions = json["questions"] as? [[String: Any]]
BTW, I prefer to extract the logic of parsing json into another method to keep fetchQuizzes method simple.
Hope this helps!

Passing data from JSON to table view cell in Swift 3

I'm trying to pass data from a JSON response to a table view cell. I'm having problems with capturing the response values that I'm extracting in URLSession.shared.dataTask.
func callYouTubeAPIToGetAllVideos() {
let url = URL(string: "https://www.googleapis.com/youtube/v3/search?part=snippet&channelId=XYZ&maxResults=50&order=date&key=ABC")
let task = URLSession.shared.dataTask(with: url!) { (data, response, error) in
if error != nil {
print(error!)
} else {
if let usableData = data {
let json = try? JSONSerialization.jsonObject(with: usableData, options: [])
if let dictionary = json as? [String: Any?] {
if let array = dictionary["items"] as? [Any] {
for object in array {
if let objectAsDictionary = object as? [String: Any?] {
if let objectWithKindAndVideoId = objectAsDictionary["id"] as? [String: String] {
if let videoId = objectWithKindAndVideoId["videoId"] {
//pass data to table cell
}
}
if let snippet = objectAsDictionary["snippet"] as? [String: Any] {
if let description = snippet["description"] {
//pass data to table cell
}
}
}
}
}
}
}
}
}
task.resume()
}
I tried appending the values to an instance variable but it didn't work.
Sorry about the messy code, this is my 1st time working with JSON in Swift.
First of all never declare a received JSON dictionary as [String:Any?]. A received dictionary value can't be nil.
Declare a custom struct Video.
struct Video {
let videoId : String
let description : String
}
Declare a data source array.
var videos = [Video]()
Parse the JSON into the array and reload the table view on the main thread.
func callYouTubeAPIToGetAllVideos() {
let url = URL(string: "https://www.googleapis.com/youtube/v3/search?part=snippet&channelId=XYZ&maxResults=50&order=date&key=ABC")
let task = URLSession.shared.dataTask(with: url!) { (data, response, error) in
if error != nil {
print(error!)
} else {
do {
if let dictionary = try JSONSerialization.jsonObject(with: data!) as? [String: Any],
let array = dictionary["items"] as? [[String: Any]] {
for object in array {
if let objectWithKindAndVideoId = object["id"] as? [String: String],
let snippet = object["snippet"] as? [String: Any] {
let videoId = objectWithKindAndVideoId["videoId"] ?? ""
let description = snippet["description"] as? String ?? ""
let video = Video(videoId: videoId, description: description)
self.videos.append(video)
}
}
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
} catch {
print(error)
}
}
}
task.resume()
}
In cellForRow assign the values to the text properties
let video = videos[indexPath.row]
cell.textLabel!.text = video.videoId
cell.detailTextLabel?.text = video.description

Can't get data from Dark Sky API

I try to get information about the weather hourly from the Dark Sky API, but the code stops working at the if let data = hourly["data"] as? [String : AnyObject] line (checked with printing stuff after every line). I want to know what is wrong with my code. I think it could be something with the "data" let, but I don't know for sure.
let Task2 = URLSession.shared.dataTask(with: urlRequestDark) { (data, response, error) in
if error == nil {
do {
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! [String : AnyObject]
if let hourly = json["hourly"] as? [String : AnyObject] {
if let data = hourly["data"] as? [String : AnyObject]{
if let hourNum = data["14"] as? [String : AnyObject] {
if let chanceRain = hourNum["precipProbability"] as? Float{
self.chanceHour1 = String(chanceRain)
}
DispatchQueue.main.sync {
self.ChanceRainLabel.text = self.chanceHour1
}
}
}
}
} catch let jsonError {
print(jsonError.localizedDescription)
}
}
}
Task2.resume() test
The strange part is, this does work:
let urlRequestDark = URLRequest(url: URL (string: "https://api.darksky.net/forecast/(API Key)/(coordinates)")!)
let Task = URLSession.shared.dataTask(with: urlRequestDark) { (data, response, error) in
if error == nil {
do{
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! [String : AnyObject]
if let currently = json["currently"] as? [String : AnyObject] {
if let chance2 = currently["precipProbability"] as? Float{
print(String(chance2))
self.chance = String(Int(chance2 * 100)) + "%"
self.PreType = currently["precipType"] as? String
}
if let _ = json["error"]{
}
DispatchQueue.main.sync{
self.TypeLabel.text = self.PreType
self.ChanceLabel.text = self.chance
}
}
}catch let jsonError{
print(jsonError.localizedDescription)
}
}
}
Task.resume()
You've made couple mistakes.
First, "data" is an array of dictionaries, so it should be cast to [[String : AnyObject]].
Second, you're trying to subscript array by String, not Int.
Third, using self in escaping closures potentially creates retain cycles.
Let me propose you some fixed and adjusted code.
let task2 = URLSession.shared.dataTask(with: urlRequestDark) { [weak self] (data, response, error) in
guard error == nil else { return }
do {
if let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? [String : AnyObject],
let hourly = json["hourly"] as? [String : AnyObject],
let data = hourly["data"] as? [[String : AnyObject]],
data.count > 14,
let chanceRain = data[14]["precipProbability"] as? Float {
self?.chanceHour1 = String(chanceRain)
DispatchQueue.main.sync {
self?.ChanceRainLabel.text = self?.chanceHour1
}
}
} catch let jsonError {
print(jsonError.localizedDescription)
}
}
task2.resume()
Try like this
import UIKit
class WebService: NSObject {
var session = URLSession()
public class var sharedInstance: WebService {
struct Singleton {
static let instance = WebService()
}
return Singleton.instance
}
override init() {
let configuration = URLSessionConfiguration.default
configuration.timeoutIntervalForRequest = 30.0
configuration.timeoutIntervalForResource = 60.0
session = URLSession(configuration: configuration)
}
public func weatherData(coordinate:String,APIkey:String,completion:#escaping (_ responsedata:NSDictionary?,_ error:NSError?) -> Void) {
var Baseurl = "https://api.darksky.net/forecast/\(APIkey)/\(coordinate)"
Baseurl = Baseurl.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!
let weatherRequestUrl = URL(string: Baseurl)
let request = NSMutableURLRequest(url: weatherRequestUrl!)
let task = session.dataTask(with: request as URLRequest) { (data, response, error) in
guard error == nil && data != nil else {
return
}
if let httpStatus = response as? HTTPURLResponse{
if httpStatus.statusCode != 200 {
print("Something is wrong")
}
}
do {
let WindlocationData = try JSONSerialization.jsonObject(with: data! as Data, options:.allowFragments) as! NSDictionary
print(WindlocationData)
completion(WindlocationData,nil)
}
catch let error as NSError {
completion(nil,error)
}
}
task.resume()
}
}
And call API like this!
func callAPI(latlong:String,APIkeyParm:String) {
WebService.sharedInstance.weatherData(coordinate: latlong,APIkey: APIkeyParm) { (responsData, error) in
if error == nil{
print("Response data is-\(responsData)")
}
}
}
Call the method like this
let latlongStr = "\(latitude),\(longitude)"
self.callAPI(latlong: latlongStr,APIkeyParm: "APIKeyString")
One importent thing you need to pass latlong like this format 23.022504999999999,72.571362100000002

Swift 3 parsing youtube videos doesn't show results and keeps loading - IOS 10

I'm trying to fetch youtube channels and videos by json parsing, and I'm new to Swift 3. However, the loading icon doesn't disappear, and no result are shown, With no errors in the log.
this is my code :
1/ func getVideosForChannelAtIndex :
func getVideosForChannelAtIndex(_ index: Int!) {
let playlistID = channelsDataArray[index]["playlistID"] as! String
let urlString = "https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&playlistId=\(playlistID)&key=\(apiKey)"
let targetURL = URL(string: urlString)
var url = URLRequest(url: targetURL!)
url.httpMethod = "GET"
URLSession.shared.dataTask(with: url) { (data, response, error) in
let httpStatus = response as? HTTPURLResponse
if httpStatus!.statusCode == 200 && error != nil {
do {
let resultsDict = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as! Dictionary<String, AnyObject>
let items: Array<Dictionary<String, AnyObject>> = resultsDict["items"] as! Array<Dictionary<String, AnyObject>>
for i in 0 ..< items.count {
let playlistSnippetDict = (items[i] as Dictionary<String, AnyObject>)["snippet"] as! Dictionary<String, AnyObject>
var desiredPlaylistItemDataDict = Dictionary<String, AnyObject>()
desiredPlaylistItemDataDict["title"] = playlistSnippetDict["title"]
desiredPlaylistItemDataDict["thumbnail"] = ((playlistSnippetDict["thumbnails"] as! Dictionary<String, AnyObject>)["default"] as! Dictionary<String, AnyObject>)["url"]
desiredPlaylistItemDataDict["videoID"] = (playlistSnippetDict["resourceId"] as! Dictionary<String, AnyObject>)["videoId"]
self.videosArray.append(desiredPlaylistItemDataDict)
self.tableView.reloadData()
}
} catch {
print(error)
}
}
else {
print("Error while loading channel videos: \(error)")
}
self.activityView.isHidden = true
}
}
2/ func getChannelDetails :
func getChannelDetails(_ useChannelIDParam: Bool) {
var urlString: String!
if !useChannelIDParam {
urlString = "https://www.googleapis.com/youtube/v3/channels?part=contentDetails,snippet&forUsername=\(desiredChannelsArray[channelIndex])&key=\(apiKey)"
}
else {
urlString = "https://www.googleapis.com/youtube/v3/channels?part=contentDetails,snippet&id=\(desiredChannelsArray[channelIndex])&key=\(apiKey)"
}
let targetURL = URL(string: urlString)
var request = URLRequest(url: targetURL!)
request.httpMethod = "GET"
URLSession.shared.dataTask(with: request) { (data, response, error) in
let httpStatus = response as? HTTPURLResponse
if httpStatus!.statusCode == 200 && error != nil {
do {
let resultsDict = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as! Dictionary<String, AnyObject>
let items: AnyObject! = resultsDict["items"] as AnyObject!
let firstItemDict = (items as! Array<AnyObject>)[0] as! Dictionary<String, AnyObject>
let snippetDict = firstItemDict["snippet"] as! Dictionary<String, AnyObject>
var desiredValuesDict: Dictionary<String, AnyObject> = Dictionary<String, AnyObject>()
desiredValuesDict["title"] = snippetDict["title"]
desiredValuesDict["description"] = snippetDict["description"]
desiredValuesDict["thumbnail"] = ((snippetDict["thumbnails"] as! Dictionary<String, AnyObject>)["default"] as! Dictionary<String, AnyObject>)["url"]
desiredValuesDict["playlistID"] = ((firstItemDict["contentDetails"] as! Dictionary<String, AnyObject>)["relatedPlaylists"] as! Dictionary<String, AnyObject>)["uploads"]
self.channelsDataArray.append(desiredValuesDict)
self.tableView.reloadData()
self.channelIndex += 1
if self.channelIndex < self.desiredChannelsArray.count {
self.getChannelDetails(useChannelIDParam)
}
else {
self.activityView.isHidden = true
}
} catch {
print(error)
}
} else {
print("Error while loading channel details: \(error)")
}
}
}
}
3/ func textFieldShouldReturn:
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
activityView.isHidden = false
var type = "channel"
if segmentDisplay.selectedSegmentIndex == 1 {
type = "video"
videosArray.removeAll(keepingCapacity: false)
}
var urlString = "https://www.googleapis.com/youtube/v3/search?part=snippet&q=\(textField.text)&type=\(type)&key=\(apiKey)"
urlString = urlString.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)!
let targetURL = URL(string: urlString)
var request = URLRequest(url: targetURL!)
request.httpMethod = "GET"
URLSession.shared.dataTask(with: request) { (data, response, error) in
let httpStatus = response as? HTTPURLResponse
if httpStatus!.statusCode == 200 && error != nil {
do {
let resultsDict = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as! Dictionary<String, AnyObject>
let items: Array<Dictionary<String, AnyObject>> = resultsDict["items"] as! Array<Dictionary<String, AnyObject>>
for i in 0 ..< items.count {
let snippetDict = items[i]["snippet"] as! Dictionary<String, AnyObject>
if self.segmentDisplay.selectedSegmentIndex == 0 {
self.desiredChannelsArray.append(snippetDict["channelId"] as! String)
}
else {
var videoDetailsDict = Dictionary<String, AnyObject>()
videoDetailsDict["title"] = snippetDict["title"]
videoDetailsDict["thumbnail"] = ((snippetDict["thumbnails"] as! Dictionary<String, AnyObject>)["default"] as! Dictionary<String, AnyObject>)["url"]
videoDetailsDict["videoID"] = (items[i]["id"] as! Dictionary<String, AnyObject>)["videoId"]
self.videosArray.append(videoDetailsDict)
self.tableView.reloadData()
}
}
} catch {
print(error)
}
if self.segmentDisplay.selectedSegmentIndex == 0 {
self.getChannelDetails(true)
}
}
else {
print("Error while loading channel videos: \(error)")
}
self.activityView.isHidden = true
}
return true
}
As mentioned in the comments you have to call resume() on each task, because all tasks of URLSession are suspended by default.
Using your one-liner this way:
URLSession.shared.dataTask(with: request) { (data, response, error) in
...
}.resume()
Alternatively
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
...
}
task.resume()
By the way the URLRequestinstances are not needed at all. GET is the default HTTP method.
Note: Make sure that all optional values embedded in the URLs with string interpolation are unwrapped otherwise you'll get literal Optional("Foo") strings. For example textField.text in the third code snippet is definitely an optional.

Deserialize JSON in swift

Is there a way to properly deserialize an json in swift that is this structure?
{
Usuario = (
{
"picture_url" = "";
id = 229;
name = "ABC";
}
);}
I tested this with jsonHelper library
let jsonData = try NSJSONSerialization.JSONObjectWithData(data!, options:NSJSONReadingOptions.MutableContainers )
let jsonString = jsonData
var mstemp = [usuario]()
mstemp <-- jsonString
but only worked for jsons this structure
{"name": "myUser", "id": "1","picture_url": ""}
Update
code:
let urlFinal = URLSERVIDOR+"/ws/rest/Geral/consultaUsuario?token=\(validotoken)&email=\(validoEmail)&senha=\(SenhaCriptada)"
let jsonUrl = urlFinal
let session = NSURLSession.sharedSession()
let shotsUrl = NSURL(string: jsonUrl)
let task = session.dataTaskWithURL(shotsUrl!) {data, response, error in
guard data != nil else {
falha()
return
}
do {
let jsonData = try NSJSONSerialization.JSONObjectWithData(data!, options:NSJSONReadingOptions.MutableContainers )
let jsonString = jsonData
var mstemp = [usuario]()
mstemp <-- jsonString
dispatch_async(dispatch_get_main_queue(),{
sucesso(usuarioBaixado: mstemp)
});
} catch _ {
falha()
}
}
task.resume()
Try this:
URLSession.shared.dataTask(with: shotsUrl!) {
(data, response, error) in
guard data != nil else {
return
}
guard let json = try? JSONSerialization.jsonObject(with: data!, options: []) as! [String: AnyObject],
let usuario = json["Usuario"] as! AnyObject else {
return
}
print ("Usuario:\n\t\(usuario["id"] as! Int)")
print ("\t\(usuario["name"] as! String)")
print ("\t\(usuario["picture_url"] as! String)")
}

Resources