Parse a JSON array - json

i am working on a way to parse json from the web in my app.
Source: http://api.randomuser.me/
My Code:
var bytes: NSMutableData?
#IBAction func loadJson(sender: AnyObject) {
let request = NSURLRequest(URL: NSURL(string: "http://api.randomuser.me/")!)
let loader = NSURLConnection(request: request, delegate: self, startImmediately: true)
}
func connection(didReceiveResponse: NSURLConnection!, didReceiveResponse response: NSURLResponse!) {
self.bytes = NSMutableData()
}
func connection(connection: NSURLConnection!, didReceiveData conData: NSData!) {
self.bytes?.appendData(conData)
}
func connectionDidFinishLoading(connection: NSURLConnection!) {
let jsonResult: Dictionary = NSJSONSerialization.JSONObjectWithData(self.bytes!, options: NSJSONReadingOptions.MutableContainers, error: nil) as! Dictionary<String, AnyObject>
let results: NSArray = jsonResult["results"]! as! NSArray
println(results)
for result in results {
// Works
println(result)
// Works
println(result["seed"])
// Does not work !!! why?
println(result["user"]["email"])
}
}
Why can't I get the email from the array?
If you want you can take a look at the json in the link above.

By using SwiftyJSON you can handle your JSON data easily this way:
#IBAction func loadJson(sender: AnyObject) {
let baseURL = NSURL(string: "http://api.randomuser.me/")
let userData = NSData(contentsOfURL: baseURL!)
let json = JSON(data: userData!)
let seeds = json["results"][0]["seed"].stringValue
let email = json["results"][0]["user"]["email"].stringValue
println(seeds) //1bbefb89fc47c81501
println(email) //luz.hidalgo44#example.com
}
Hope this will help.

Related

JSONSerialization to SwiftyJSON

I am trying to use SwiftyJSON with my JSON api data but am having trouble understanding how the conversion works.
Here is a link to the SwiftyJSON Git: https://github.com/SwiftyJSON/SwiftyJSON
Here is my current code:
func newFilms() {
let apiKey = "12345"
let url = URL(string: "https://api.themoviedb.org/3/movie/now_playing?api_key=\(apiKey)&language=en-US&page=1")
let request = URLRequest(
url: url! as URL,
cachePolicy: URLRequest.CachePolicy.reloadIgnoringLocalCacheData,
timeoutInterval: 10 )
let session = URLSession (
configuration: URLSessionConfiguration.default,
delegate: nil,
delegateQueue: OperationQueue.main
)
let task = session.dataTask(with: request, completionHandler: { (dataOrNil, response, error) in
if let data = dataOrNil {
if let resposeDictionary = try! JSONSerialization.jsonObject(with: data, options:[]) as? [String: Any] {
self.films = (resposeDictionary["results"] as? [String: Any])!
print("response: \(resposeDictionary)")
}
}
self.filteredFilms = self.films
self.filmsCollection.reloadData()
})
task.resume()
}
Here is the example of the new SwiftyJSON:
let json = JSON(data: dataFromNetworking)
if let userName = json[0]["user"]["name"].string {
print("\(userName)")
//Now you got your value
}
My main question is, what would go where it says data: datafromNetworking, I am confused what part of the original code should be implemented and how to use it for the new version.
dataFromNetworking represents the data object returned from the dataTask. SwiftyJSON does the deserialization.
Replace
if let data = dataOrNil {
if let resposeDictionary = try! JSONSerialization.jsonObject(with: data, options:[]) as? [String: Any] {
self.films = (resposeDictionary["results"] as? [String: Any])!
print("response: \(resposeDictionary)")
}
}
with
if let data = dataOrNil {
do {
let json = try JSON(data: data)
self.films = json["results"].dictionaryValue
} catch { print(error) }
}
However in Swift 4 SwiftyJSON became obsolete in favor to the powerful built-in Codable protocol

Struct Init with JSON and flatMap

I'm having a problem with the following code. I'm downloading a list of actors in JSON and I want to populate Struct Actor with the received data. Everything works great until I try to flatMap on the received data and try to initialize the struct Actor. When I try to compile the code i get the error: Cannot assign value of type '()' to type [Actor]. The error corresponds to a line in viewDidLoad actorsList = downloadActors() Would anybody have any recommendation who to solve this?
import UIKit
func downloadActors() {
var request = URLRequest(url: URL(string: "url...")!)
request.httpMethod = "POST"
let postString = "actorGroup=\("Superhero")"
request.httpBody = postString.data(using: .utf8)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
DispatchQueue.main.async {
guard let data = data, error == nil else {
print("error=\(error)")
return
}
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {
print("error : statusCode should be 200 but is \(httpStatus.statusCode)")
print("response = \(response)")
}
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode == 200 {
do {
let json = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.mutableContainers) as? [String: AnyObject]
guard let actorsJSON = json?["response"] as? [[String : AnyObject]] else {
return
}
} catch {
print("catch error")
}
}
}
}
task.resume()
}
func loadActors() -> [Actor] {
if let actors = actorsJSON as? [[String : AnyObject]] {
return actors.flatMap(Actor.init)
}
}
let actorsArray = loadActors()
class MasterViewController: UITableViewController {
var actorsList = [Actor]()
var detailViewController: DetailViewController? = nil
var objects = [Any]()
override func viewDidLoad() {
super.viewDidLoad()
actorsList = downloadActors()
print(actorsList)
Struct Actors is as follows:
struct Job {
let actorGroup: String
let actorName: String
}
extension Actor: JSONDecodable {
init?(JSON: [String : AnyObject]) {
guard let actorGroup = JSON["actorGroup"] as? String, let actorName = JSON["actorName"] as? String else {
return nil
}
self. actorGroup = actorGroup
self. actorName = actorName
}
}
let listActors = actorsJSON as? [[String : AnyObject]] {
Should be:
if let listActors = actorsJSON as? [[String : AnyObject]] {
Edit: For more info I'd like to add Vadian's comment:
Very confusing code. What does the function in the middle of the do block? Why do you type-check actorsJSON twice? The computed property is let listActors... which should be probably an optional binding (if let ... ). Further .mutableContainers is completely nonsense in Swift. And finally a JSON dictionary is [String:Any] in Swift 3.

Error when try to parse json?

I'm trying to parse JSON, but it's not working. I want to get id from the JSON at the URL, but it shows me null value.
var names = [String]()
var SearchURL = "http://ios.khothe.vn/web/gamecards/authenticate/user/dungphiau/pass/829d81d46bad96825dc52a6e1675aab0"
typealias jsonStandard = [String : AnyObject]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
callAlamo(url: SearchURL)
}
func callAlamo(url : String) {
Alamofire.request(url).responseJSON(completionHandler:
{
responds in
self.parseData(JsonData: responds.data!)
})
}
func parseData(JsonData : Data) {
do{
var readableJson = try JSONSerialization.jsonObject(with: JsonData, options: .mutableContainers) as! jsonStandard
let tracks = readableJson["id"] as? jsonStandard
print(tracks)
} catch{
print(error)
}
}
The value for key id is String not [String:AnyObject] aka jsonStandard
let tracks = readableJson["id"] as? String
Consider that in Swift 3 the type of a JSON dictionary is [String:Any]
typealias jsonStandard = [String : Any]

json data not getting loaded into UITextView in swift

class ViewController:ViewController,UITextViewDelegate{
#IBOutlet weak var newTextView: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
newTextView.delegate = self
dataFun()
}
func dataFun()
{
let url : String = "http:xyz/abc"
let request : NSMutableURLRequest = NSMutableURLRequest()
request.URL = NSURL(string: url)
request.HTTPMethod = "GET"
print("Start")
let session = NSURLSession.sharedSession()
session.dataTaskWithRequest(request) { (data, response, error) -> Void in
do {
let jsonResult: NSDictionary! = try NSJSONSerialization.JSONObjectWithData(data!, options:NSJSONReadingOptions.MutableContainers) as? NSDictionary
print("In method\(jsonResult)")
// let data = jsonResult["description"]
// print(data!)
if (jsonResult != nil)
{
// process jsonResult
print("Data added")
let test:String = jsonResult["description"] as! String
print(test)
self.newTextView.text = test
} else {
print("No Data")
// couldn't load JSON, look at error
}
}
catch {
print("Error Occured")
}
}
.resume()
}
In my app I am going to call services from API
I can see my json data in console.
that data is not show in textviewController
it shows fatal error:
unexpectedly found nil while unwrapping an Optional value
and then crash the app
Make sure #IBOutlet weak var newTextView: UITextView! is set up correctly.
Make sure let test:String = jsonResult["description"] as! String doesn't crash. JSON has field description and it's a string.

Get JSON in Swift

This is my code to get JSON, and it's work with this url I found on an other questions : http://binaenaleyh.net/dusor/.
But, when I use it with this url : http://www.netcampus.fr/api/schools, it didn't work at all. I have an error who said : "exc_breakpoint (code=exc_i386_bpt subcode=0x0)"
Is my code wrong, or is it the JSON data ?
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
var myData:NSData = getJSON("http://www.netcampus.fr/api/schools")
println(myData) // show me data
var myDict:NSDictionary = parseJSON(myData)
println(myDict)
}
func getJSON(urlToRequest: String) -> NSData{
return NSData(contentsOfURL: NSURL(string: urlToRequest))
}
func parseJSON(inputData: NSData) -> NSDictionary{
var error: NSError?
var boardsDictionary: NSDictionary = NSJSONSerialization.JSONObjectWithData(inputData, options: NSJSONReadingOptions.MutableContainers, error: &error) as NSDictionary // error here
return boardsDictionary
}
}
Your parseJSON method crashes when parsing the second JSON. NSJSONSerialization maps its contents to an array and you are expecting a dictionary:
var boardsDictionary: NSDictionary = NSJSONSerialization.JSONObjectWithData(inputData, options: NSJSONReadingOptions.MutableContainers, error: &error) as NSDictionary // error here
As #reecon pointed out ,your code should be like this
//JSON Parsing
func JSONParsingSample() {
var myData:NSData = getJSON("http://www.netcampus.fr/api/schools")
//println(myData) // show me data
var myDict:NSArray = parseJSON(myData)
println(myDict)
}
func getJSON(urlToRequest: String) -> NSData{
return NSData(contentsOfURL: NSURL(string: urlToRequest))
}
func parseJSON(inputData: NSData) -> NSArray{
var error: NSError?
var boardsDictionary: NSArray = NSJSONSerialization.JSONObjectWithData(inputData, options: NSJSONReadingOptions.MutableContainers, error: &error) as NSArray
return boardsDictionary
}
//end
let urlString = "webAPI"
var request = URLRequest(url: URL(string: urlString)!)
let session = URLSession.shared
request.httpMethod = "GET"
session.dataTask(with: request)
{
data, response, error in
if error != nil
{
print(error!.localizedDescription)
return
}
do
{
let jsonResult: NSDictionary? = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers) as? NSDictionary
self.dict = jsonResult as! NSMutableDictionary
print("Synchronous\(jsonResult)")
DispatchQueue.main.async
{
let url = URL(string: ((((self.dict.value(forKey: "sources") as! NSArray).object(at: 5) as! NSDictionary).value(forKey: "urlsToLogos") as? NSDictionary)?.value(forKey: "small") as? String)!)
let data = try? Data(contentsOf: url!)
}
}
catch
{
print"error"
}
}.resume()