func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
let urlRequest = URLRequest(url: URL(string: "https://www.googleapis.com/youtube/v3/channels?part=id&forUsername=\(searchBar.text!.replacingOccurrences(of: " ", with: "%20"))&key=1234")!)
let task = URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in
if error == nil {
do {
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! [String : AnyObject]
if let items = json["items"] as? [String : AnyObject] {
if let id = items["id"] as? Int {
self.id = id
}
}
if let _ = json["error"] {
self.exists = false
}
DispatchQueue.main.async {
if self.exists{
print("\(self.id)")
}else {
self.exists = true
}
}
} catch let jsonError {
print(jsonError.localizedDescription)
}
}
}
task.resume()
}
I want to get the Youtube channel id from google analytics but it keeps saying "nil". I am not sure what i am doing wrong because everything works the same on my website! Please help! Thanks
When I use your code, the JSON I get back is
{
"kind": "youtube#channelListResponse",
"etag": "\"m2yskBQFythfE4irbTIeOgYYfBU/uX-2P6nRpmv4I_ZWtiIyofqF5ss\"",
"pageInfo": {
"totalResults": 1,
"resultsPerPage": 5
},
"items": [
{
"kind": "youtube#channel",
"etag": "\"m2yskBQFythfE4irbTIeOgYYfBU/3W7RccGn0o-nTtgCGrEvd-AbX6Y\"",
"id": "UCfpqR6vgT_mzWrbXcTYxL8w"
}
]
}
So, items["id"] is not an Int. Try
if let id = items["id"] as? String
instead
Also, change self.id to a String.
UPDATED:
Also,
if let items = json["items"] as? [String : AnyObject] {
won't work because items is an array of dictionaries.
You need
if let items = json["items"] as? [[String : AnyObject]] {
and then,
if let id = items[0]["id"] as? String
You should probably check the items.count, but you can do that once you get this working.
Related
Can somebody help with parsing this kind of JSON object?
{
"array":[
{
"title":"",
"desc":""
},
{
"title":"",
"desc":""
},
{
"title":"",
"desc":""
}
]
}
My code doesnt work
let task = self.session.dataTask(with: url) {
data, response, error in
if let data = data,
let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] {
for case let announcment in json!["array"]{
guard let title = announcment["title"] as? String,
let description = announcment["desc"] as? String,
else{ return }
}
task.resume()
Thank in advance for any help!
Pretty-printing your JSON makes it easier to work through:
{
"array":[
{
"title":"",
"desc":""
},
{
"title":"",
"desc":""
},
{
"title":"",
"desc":""
}
]
}
You need to get the array first. An array of dictionaries is of type [[String: Any]].
let task = self.session.dataTask(with: url) {
data, response, error in
if let data = data,
let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] {
guard let announcements = json["array"] as? [[String: Any]]
else { return }
announcements.forEach { announcement in
guard let title = announcement["title"] as? String,
let description = announcement["desc"] as? String
else { return }
// Do something with the result
}
}
}
task.resume()
You can structure your data and make it Codable:
struct Root: Codable {
let array: [Announcement]
}
struct Announcement: Codable {
let title: String
let desc: String
}
let data = Data("""
{"array":[{"title":"","desc":""},{"title":"","desc":""},{"title":"","desc":""}]}
""".utf8)
do {
let announcements = try JSONDecoder().decode(Root.self, from: data).array
for announcement in announcements {
print(announcement)
}
} catch {
print(error)
}
This will print
Announcement(title: "", desc: "")
Announcement(title: "", desc: "")
Announcement(title: "", desc: "")
I recently began with swift. I need decode the json on below.
The JSON has inside two more JSON the first one (validation) does not matter. The second one (result) has a JSON array inside (serviceCenter). I need the information of each servicenter. I try to use servicecenter as decodeable class to get a servicenter object, but as the JSON does not have the proper format I can't do it.
[
{
"validation": {
"bValid": true,
"sDescription": "Access true."
}
},
{
"result": {
"serviceCenter": [
{
"model": "Vanquish",
"color": "Purple",
"make": "Aston Martin",
"sTag": "3666",
"sVin": "6JDO2345",
"sMiles": "3666",
"bDamage": "1",
"dDateTime": "04-17-2018 9:38 AM"
},
{
"model": "F360",
"color": "Red",
"make": "Ferrari",
"sTag": "0010",
"sVin": "6JDO2347",
"sMiles": "80000",
"bDamage": "1",
"dDateTime": "04-17-2018 9:25 AM"
},
{
"model": "Vanquish",
"color": "Purple",
"make": "Aston Martin",
"sTag": "0009",
"sVin": "6JDO2345",
"sMiles": "25000",
"bDamage": "1",
"dDateTime": "04-17-2018 9:23 AM"
},
{
"model": "Vanquish",
"color": "Purple",
"make": "Aston Martin",
"sTag": "0003",
"sVin": "6JDO2345",
"sMiles": "20000",
"bDamage": "1",
"dDateTime": "04-12-2018 10:37 AM"
}
]
}
}
]
I try so much but i cant do it.
This its my code now, Could someone help me please
do {
let parseoDatos = try JSONSerialization.jsonObject(with: data!) as! [AnyObject]
let h = type(of: parseoDatos )
print("'\(parseoDatos)' of type '\(h)'")
let contenido = parseoDatos[1]["result"]
if let services = contenido!! as? Dictionary<String, Array<Any>> {
for (_,serviceArray) in services {
for sc in serviceArray{
let h = type(of: sc )
print("'\(sc)' of type '\(h)'")
}
}
}
} catch {
print("json processing failed")
}
the result of print sc is
{
bDamage = 1;
color = Purple;
dDateTime = "04-17-2018 9:38 AM";
make = "Aston Martin";
model = Vanquish;
sMiles = 3666;
sTag = 3666;
sVin = 6JDO2345;
}' of type '__NSDictionaryI'
You can use Codable
Initial response have array of InitialElement and InitialElement is is struct with validation , result , result may be nil
don't forget to add your URL at url
URLSession.shared.dataTask(with: url!) { (data, response, error) in
if let initial = try? JSONDecoder().decode([InitialElement].self, from: data){
// inital now have array of InitialElement and InitialElement is is struct with validation , result , result may be nil
print(initial)
}
}.resume()
With this Model for Data:
import Foundation
struct InitialElement: Codable {
let validation: Validation?
let result: ResultData?
}
struct ResultData: Codable {
let serviceCenter: [ServiceCenter]
}
struct ServiceCenter: Codable {
let model, color, make, sTag: String
let sVin, sMiles, bDamage, dDateTime: String
}
struct Validation: Codable {
let bValid: Bool
let sDescription: String
}
extension InitialElement {
init(data: Data) throws {
self = try JSONDecoder().decode(InitialElement.self, from: data)
}
}
try this code
enum ParsingError: Error {
case wrongFormat(String)
}
do {
let jsonObject = try JSONSerialization.jsonObject(with: data!)
guard let array = jsonObject as? [Any] else {
throw ParsingError.wrongFormat("wrong root object")
}
guard array.count == 2 else {
throw ParsingError.wrongFormat("array count != 2")
}
guard let dict = array[1] as? [String: Any] else {
throw ParsingError.wrongFormat("can't parse dict from array")
}
guard let serviceCenters = (dict["result"] as? [String: Any])?["serviceCenter"] else {
throw ParsingError.wrongFormat("can't parse serviceCenters")
}
guard let serviceCentersArray = serviceCenters as? [[String : Any]] else {
throw ParsingError.wrongFormat("serviceCenters is not an array")
}
print("\(type(of: serviceCentersArray))\n", serviceCentersArray)
} catch {
print("json processing failed: \(error)")
}
Thanks all for yours answers, it's my first question here, and i feels great all the help. Finally i can resolve the problem. Maybe not the best way, but here its the code:
let task = URLSession.shared.dataTask(with: request) { (data: Data?, response: URLResponse?, error: Error?) in
if error != nil{
print("error=\(String(describing: error))")
return
}
do {
let parseoDatos = try JSONSerialization.jsonObject(with: data!) as! [AnyObject]
let h = type(of: parseoDatos )
print("'\(parseoDatos)' of type '\(h)'")
let contenido = parseoDatos[1]["result"]
if let services = contenido!! as? Dictionary<String, Array<Any>> {
for (_,serviceArray) in services {
for sc in serviceArray{
let h = type(of: sc )
print("'\(sc)' of type '\(h)'")
let valid = JSONSerialization.isValidJSONObject(sc) // true
print(valid)
do {
let jsonData = try JSONSerialization.data(withJSONObject: sc, options: .prettyPrinted)
let serviceDecoded = try JSONSerialization.jsonObject(with: jsonData, options: [])
if let scJSON = serviceDecoded as? [String:String] {
print ("--------------------------")
print("'\(scJSON)' of type '\(type(of: scJSON))'")
print ("--------------------------")
}
} catch {
print(error.localizedDescription)
}
i think later y try to use Codable as suggested, but for now the code is working ok. Thanks again!
//try this it is working
let arrayMain=try?JSONSerialization.jsonObject(with:jsonData!,options:.mutableLeaves) as! Array<Any>
//print(arrayMain!)
if let firstDictionart=arrayMain![0] as? [String: Any] {
if let insideFirstDict = firstDictionart["validation"] as? [String: Any]{
print(insideFirstDict["bValid"]!)
print( insideFirstDict["sDescription"]!)
}
}
if let resultDictionary=arrayMain![1] as? [String: Any] {
if let serviceDictionary = resultDictionary["result"] as? [String: Any] {
for array in serviceDictionary["serviceCenter"] as! Array<Any>{
if let infoDicti=array as? [String: Any] {
print( infoDicti["color"]!)
print( infoDicti["make"]!)
print( infoDicti["color"]!)
print( infoDicti["sTag"]!)
print( infoDicti["sVin"]!)
print( infoDicti["sMiles"]!)
print( infoDicti["sVin"]!)
print( infoDicti["model"]!)
print( infoDicti["bDamage"]!)
print( infoDicti["dDateTime"]!)
}
}
}
}
I am learning Swift, and I am encountering an issue parsing a JSON file from a URL file.
I'm trying to call the posts dictionary and parse the audio values from it.
let url = URL(string: "https://api.myjson.com/bins/91nzd")
URLSession.shared.dataTask(with:url!, completionHandler: {(data, response, error) in
guard let data = data, error == nil else { return }
do {
let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as! [String:Any]
let posts = json["posts"] as? [String: Any] ?? [:]
print(posts)
let audios = posts["audio"] as? [String: Any] ?? [:]
print(audios)
} catch let error as NSError {
print(error)
}
}).resume()
This returns :, : which I believe is a nil expression. The JSON file it is calling looks like this:
{
"posts": [
{
"id": "1",
"title": "title 1",
"audio": "https://rss-example.com/episodes/871ae23d.mp3"
},
{
"id": "2",
"title": "title 2",
"audio": "https://rss-example.com/episodes/352ae29d.mp3"
}
]
}
This looks right to me from the tutorials I have read, but do you see an error? Or am I misinterpreting?
Mistake is posts are Array type, try this:
let url = URL(string: "https://api.myjson.com/bins/91nzd")
URLSession.shared.dataTask(with:url!, completionHandler: {(data, response, error) in
guard let data = data, error == nil else { return }
do {
let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as! [String:Any]
if let posts = json["posts"] as? Array {
for (index, element) in posts.enumerate() {
let audios = element["audio"] as? [String: Any] ?? [:]
print(audios)
}
}
} catch let error as NSError {
print(error)
}
}).resume()
Following on from This question
I am trying to bring in the summary field but it has a further value. I have brought in the title and author as follows:
func parseData(JSONData : Data) {
do {
var readableJSON = try JSONSerialization.jsonObject(with: JSONData, options: .mutableContainers) as! JSONstandard
// print(readableJSON)
if let posts = readableJSON["posts"] as? [JSONstandard] {
for post in posts {
let title = post["title"] as! String
let author = post["author"] as! String
let summary = post["summary"] as! String
print(author)
if let imageUrl = post["image"] as? String {
let mainImageURL = URL(string: imageUrl )
let mainImageData = NSData(contentsOf: mainImageURL!)
let mainImage = UIImage(data: mainImageData as! Data)
postsinput.append(postinput.init(mainImage: mainImage, name: title, author: author, summary: summary))
}
}
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
}
catch {
print(error)
}
}
But if i try the summary that way a error is returned. Any help would be appreciated.
JSON STRUCTURE
{
"posts" : [{
"id": "000000",
"url": "/content/interview2",
"date": "2016-11-03 09:01:41",
"modified": "2016-11-03 09:03:47",
"title": "An interview",
"image": "https://www.example.com/sites/default/files/oregood.jpeg",
"summary": {
"value": "<p>Latin text here</p>",
"format": "filtered_html"
}
}]
}
From your previous question response, summary key contains the Dictionary so you can try like this.
guard let dic = post["summary"] as? [String: Any], let summary = dic["value"] as? String else {
return
}
I've been trying to make this to work for two weeks now. It was working on iOS 9 with Swift 2 but now this doesn't seem to work for no reason. I've added print("[DEBUG] I was here 1/2/3/4") to debug the code and all it prints out is [DEBUG] I was here 1. Any ideas? It drives me crazy.
func downloadData() {
//clear the arrays
arrayPosts = [String]()
arrayLinks = [String]()
arrayConditions = [String]()
arrayIDs = [String]()
//debug
print("[DEBUG] I was here: 1")
//baseURL is a string with URL to JSON Endpoint
let url = URL(string: baseURL)
URLSession.shared.dataTask(with:url!, completionHandler: {(data, response, error) in
if error != nil {
print("[ERROR] [DEBUG] Error with connection: \(error)")
} else {
do {
//debug
print("[DEBUG] I was here: 2")
if let json = try JSONSerialization.jsonObject(with: data!, options:[.mutableContainers, .allowFragments]) as? [[String: Any]] {
for item in json {
//debug
print("[DEBUG] I was here: 3")
if let startTime = item["current_time"] as? Int {
if self.defaults.integer(forKey: "startTime") == 0 {
self.defaults.set(startTime, forKey: "startTime")
}
}
if let posts = item["posts"] as? [[String: AnyObject]] {
//debug
print("[DEBUG] I was here: 4")
for post in posts {
if let text = post["text"] as? String {
if let condition = post["conditions"] as? String{
if let url = post["url"] as? String {
if let id = post["id"] as? String {
self.arrayPosts.append(text)
self.arrayConditions.append(condition)
self.arrayLinks.append(url)
self.arrayIDs.append(id)
}
}
}
}
}
}
}
}
} catch {
print("[ERROR] [DEBUG] Something went wrong during data download from the server.")
}
}
}).resume()
}
Here's JSON DATA just in case:
{
"status": "ok",
"num_results": "4",
"current_time": 1474386061,
"user_time": 0,
"posts": [
{
"text": "If your shirt isn't tucked into your pants, then your pants are tucked into your shirt.",
"conditions": "4",
"url": "0",
"time": "0",
"id": "108"
},
{
"text": "Veteran Kills Himself in Parking Lot of V.A. Hospital on Long Island",
"conditions": "6",
"url": "http://www.nytimes.com/2016/08/25/nyregion/veteran-kills-himself-in-parking-lot-of-va-hospital-on-long-island.html",
"time": 1472076000,
"id": "1472076000"
},
{
"text": "Leaked Script Shows What Advisers Want Donald Trump to Say at Black Church",
"conditions": "6",
"url": "http://www.nytimes.com/2016/09/02/us/politics/donald-trump-black-voters-wayne-jackson.html",
"time": 1472767200,
"id": "1472767200"
},
{
"text": "Creepy Clown Sightings in South Carolina Cause a Frenzy",
"conditions": "6",
"url": "http://www.nytimes.com/2016/08/31/us/creepy-clown-sightings-in-south-carolina-cause-a-frenzy.html",
"time": 1472594400,
"id": "1472594400"
}
]
}
Try below code :
import UIKit
class ViewController: UIViewController {
var arrayPosts = [String]()
var arrayLinks = [String]()
var arrayConditions = [String]()
var arrayIDs = [String]()
override func viewDidLoad() {
super.viewDidLoad()
self.downloadData()
}
func downloadData()
{
let url = NSURL(string: "http://getmydetails.pe.hu/test/parsejsonswift3.php") //Provided JSON data on my server. i don't know how longer it is present there!.
let request = NSMutableURLRequest(url: url! as URL)
let task = URLSession.shared.dataTask(with: request as URLRequest) { data,response,error in
guard error == nil && data != nil else
{
print("Error:",error)
return
}
let httpStatus = response as? HTTPURLResponse
if httpStatus!.statusCode == 200
{
if data?.count != 0
{
let responseString = try! JSONSerialization.jsonObject(with: data!, options: .allowFragments) as! NSDictionary //because JSON data started with dictionary. Not an array
let status = responseString["status"] as! String
if status == "ok"
{
print("Status is :", status)
let timevar = responseString["current_time"] //not specified as String or Int
print(String(describing: timevar)) // print by converting anyobject to string
if let posts = responseString["posts"] as? [AnyObject] // posts started with array
{
for post in posts
{
let text = post["text"] as! String //specify as String
print(text)
let condition = post["conditions"] as! String
let url = post["url"] as! String
let id = post["id"] as! String
DispatchQueue.main.sync
{
self.arrayPosts.append(text)
self.arrayConditions.append(condition)
self.arrayLinks.append(url)
self.arrayIDs.append(id)
//optional to check
self.afterJSON()
}
}
}
else
{
print("I could not find post array")
}
}
else
{
print("Status is not Okay!")
}
}
else
{
print("No data got from url!")
}
}
else
{
print("error httpstatus code is :",httpStatus!.statusCode)
}
}
task.resume()
}
func afterJSON()
{
print("Posts are:\n\t\t",arrayPosts)
print("Conditions are:\n\t\t",arrayConditions)
print("Links are:\n\t\t",arrayLinks)
print("ID's are:\n\t\t",arrayIDs)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Output is like below screenshot,
If you confuse then see my video is for you.
If any queries please comment below :D
func downloadData() {
//clear the arrays
arrayPosts = [String]()
arrayLinks = [String]()
arrayConditions = [String]()
arrayIDs = [String]()
//debug
print("[DEBUG] I was here: 1")
//baseURL is a string with URL to JSON Endpoint
let url = URL(string: baseURL)
let session = URLSession.shared
let task = session.dataTask(with: url!) { (data:Data?, response:URLResponse?, error:Error?) in
if error != nil {
print("[ERROR] [DEBUG] Error with connection: \(error)")
} else {
do {
//debug
print("[DEBUG] I was here: 2")
if let json = try JSONSerialization.jsonObject(with: data!, options:[.mutableContainers, .allowFragments]) as? [[String: Any]] {
for item in json {
//debug
print("[DEBUG] I was here: 3")
if let startTime = item["current_time"] as? Int {
if self.defaults.integer(forKey: "startTime") == 0 {
self.defaults.set(startTime, forKey: "startTime")
}
}
if let posts = item["posts"] as? [[String: AnyObject]] {
//debug
print("[DEBUG] I was here: 4")
for post in posts {
if let text = post["text"] as? String {
if let condition = post["conditions"] as? String{
if let url = post["url"] as? String {
if let id = post["id"] as? String {
self.arrayPosts.append(text)
self.arrayConditions.append(condition)
self.arrayLinks.append(url)
self.arrayIDs.append(id)
}
}
}
}
}
}
}
}
} catch {
print("[ERROR] [DEBUG] Something went wrong during data download from the server.")
}
}
}
task.resume()
}
thanks man I follow your code an got data))
func getJSON(){
let wUrl = "http://api.fixer.io/latest"
let Url = NSURL(string: wUrl)
let request = NSMutableURLRequest(url: Url! as URL)
let task = URLSession.shared.dataTask(with: request as URLRequest){ data, response, error in
guard error == nil && data != nil else
{
print("Error:", error ?? "some error")
return
}
let httpStatus = response as? HTTPURLResponse
if httpStatus!.statusCode == 200 {
if data?.count != 0 {
let resposeString = try! JSONSerialization.jsonObject(with: data!, options: .allowFragments) as! NSDictionary
let base = resposeString["base"] as? String
print(base ?? "")
let date = resposeString["date"] as? String
print(date ?? "")
let rates = resposeString["rates"] as! Dictionary<String, AnyObject>
for (key, value) in rates{
print("\(key)->\(value)")
}
}
else
{
print("Data is emty")
}
}
else {
print("error httpStatus code: ", httpStatus?.statusCode ?? "")
}
};task.resume()
}