how to read data from json in swift2 - json

I am trying to read email from a json file in swift(2.2) which is:
{ "employees" : [
{
"name": "sudhanshu",
"email": "sudhanshu.bharti#digitalavenues.com",
"password": "password"
"profilePic": ""
},
{
"name": "prokriti",
"email": "prokriti.roy#digitalavenues.com",
"password": "password#123",
"profilePic": ""
}
]}
But i am getting error " Error Domain=NSCocoaErrorDomain Code=3840 "Unescaped control character around character 128." UserInfo={NSDebugDescription=Unescaped control character around character 128.}" i have seen earlier posts but unable to find where exactly problem is??
if let path = NSBundle.mainBundle().pathForResource("Employees", ofType: "json") {
if let data = NSData(contentsOfFile: path) {
do {
let jsonResult: NSDictionary = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers) as! NSDictionary
if let error = jsonResult["error"] {
print("Error is: \(error)")
} else {
if let person = jsonResult["email"] {
print(person) // dictionary[#"quotables"]
}
}
} catch let error as NSError {
print("Error is: \(error)")
}
}
}
Thanks in advance!

"password": "password”
should be
"password": "password"
You have an invalid ” character instead of a ".
Update
Now that you've fixed your invalid character, you can access your data. But you're trying to cast as an NSDictionary something that's actually an array, if I believe the JSON excerpt you showed us.
So you should do something like this instead in your do:
if let jsonResult = try NSJSONSerialization.JSONObjectWithData(data, options: []) as? [[String: String]] {
for jsonDictionary in jsonResult {
if let person = jsonDictionary["email"] {
print(person)
}
}
}
Update and fix
if let jsonResult = try NSJSONSerialization.JSONObjectWithData(data, options: []) as? [String: AnyObject] {
if let employees = jsonResult["Employees"] as? [[String:String]] {
for employee in employees {
if let person = employee["email"] {
print(person)
}
}
}
}

You are trying to access directly email key from the dictionary. while you need to first access array from the key "employees" & then you need to get value from "email" key.
if let path = NSBundle.mainBundle().pathForResource("Employees", ofType: "json") {
if let data = NSData(contentsOfFile: path) {
do {
let jsonResult: NSDictionary = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers) as! NSDictionary
if let error = jsonResult["error"] {
print("Error is: \(error)")
} else {
let person = jsonResult["employees"] as! NSArray
for i in 0..<person.count
{
let dict = person.objectAtIndex(i) as! NSDictionary
let strEmail = dict["email"] as! String
print(strEmail)
}
}
} catch let error as NSError {
print("Error is: \(error)")
}
}

Related

Get data from array in response in Swift

i'm hitting an API and response is shown like this,
"responseBody": {
"data": [
"{\"AED_USD\":0.272255,\"USD_AED\":3.67305}"
]
}
I'm confuse that how i can take out value of AED_USD and USD_AED from this array data. I have try to take all of the response in array and try to get value from index base but isn't working. How i can get the value? My code is this,
let params = ["sourceCurrency":self.accountFromTxt.text!,
"targetCurrency":self.accountToTxt.text!] as [String : AnyObject]
print(params)
APIService.ExchangePrice(showActivityIndicator: true, parameters: params) { (responseObject) in
if (responseObject?.status)!
{
self.print(responseObject?.data)
self.exchangeRateArray.removeAll()
if let usersDataArray = responseObject?.data as? [[String : Any]] {
for userData in usersDataArray {
self.exchangeRateArray.append(ExchangeRateCurrency(JSON:userData)!)
}
if usersDataArray.count == 0
{
//Empty Message
self.view.showEmptyScreenMessage(text: EmptyScreenMessages.transactionDetailMessage)
}
self.print(self.exchangeRateArray.count,self.exchangeRateArray[0])
}
}
else
{
Utilities.showBar(text: responseObject?.errorObject?.message)
}
}
Your data is in string form, change string to JSON NSdictonary.
try to convert like this
let str = "{\"AED_USD\":0.272257,\"USD_AED\":3.673001}"
if let data = str.data(using: String.Encoding.utf8) {
do {
let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String:Any]
print(json)
} catch {
print("Something went wrong")
}
}
// In your code.
let params = ["sourceCurrency":self.accountFromTxt.text!,
"targetCurrency":self.accountToTxt.text!] as [String : AnyObject]
print(params)
APIService.ExchangePrice(showActivityIndicator: true, parameters: params) { (responseObject) in
if (responseObject?.status)!
{
self.print(responseObject?.data)
self.exchangeRateArray.removeAll()
if let usersDataArray = responseObject?.data as? [[String : Any]] {
for userData in usersDataArray {
print(userData)
// if you get string from userData
if let data = userData.data(using: String.Encoding.utf8) {
do {
let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String:Any]
print(json)
} catch {
print("Something went wrong")
}
}
}
if usersDataArray.count == 0
{
//Empty Message
self.view.showEmptyScreenMessage(text: EmptyScreenMessages.transactionDetailMessage)
}
//self.print(self.exchangeRateArray.count,self.exchangeRateArray[0])
}
}
else
{
Utilities.showBar(text: responseObject?.errorObject?.message)
}
}

Swift 3 json parsing

I am running into troubles updating my app as Alamofire and SwiftyJSON are not yet supporting Swift 3. I have a url that would return me json as follows:
{
"products": [
{
"body_html":"",
"created_at":"2016-03-02T13:56:18+03:00",
"id":489759251,
"handle":"product",
"options":[
{
"id":627488838,
"product_id":489759251,
"name":"Title",
"position":1,
"values":[
"Default Title"
]
}
],
},
{
"body_html":"",
"created_at":"2016-03-08T05:17:55+03:00",
"id":530420915,
"handle":"product-2",
"options":[
{
"id":6319359750,
"product_id":530420915,
"name":"Title",
"position":1,
"values":[
"Default Title"
]
}
],
},
]
}
I need to be able to parse that json and list all returned products and be able to read any specific attribute and sub options of each.
I checked some other questions here and found several solutions and was able to get the json data and printed it as above. But, I couldn't parse it.
let shopUrl = "https://\(apiKey):\(password)#\(hostname)" + "/admin/products.json"
let url = URL(string: shopUrl)
URLSession.shared.dataTask(with:url!, completionHandler: {(data, response, error) in
if error != nil {
print(error)
} else {
do {
let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as! [String:Any]
print(json)
} catch let error as NSError {
print(error)
}
}
}).resume()
Any help?
To loop over all of the products you need to extract and cast it to the correct type. In this case an array of [String: Any].
I extracted the relevant bit of code and cleaned it up a bit to make this answer more readable.
guard let json = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String: Any],
let products = json["products"] as? [[String: Any]]
else { return }
for product in products {
guard let id = product["id"] as? Int,
let options = product["options"] as? [[String: Any]]
else { return }
print(id)
print(options)
}
This parses the JSON, the root object is a dictionary, the objects for products and options are arrays. One value respectively is printed as an example.
if let jsonObject = try JSONSerialization.jsonObject(with:data, options: []) as? [String:Any] {
print(jsonObject)
if let products = jsonObject["products"] as? [[String:Any]] {
for aProduct in products {
print(aProduct["created_at"])
if let options = aProduct["options"] as? [[String:Any]] {
for option in options {
print(option["product_id"])
}
}
}
}
}

How do I get values from a complex JSON object?

Is it possible that someone could show me how to get the names of these pizza places printing out? My application prints out the expected "Status Code: 200". However, my console only shows empty brackets []. I suspect that I am not pulling values from my JSON object properly.
I'm using this link for my API.
Link For API
Question
How can I properly fetch values from my serialized JSON object?
relevant code:
// Response
if let httpResponse = response as? NSHTTPURLResponse where httpResponse.statusCode == 200, let data = data {
print("Status Code: \(httpResponse.statusCode)")
do {
let json = try NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers)
if let pizzaPlaces = json["response"] as? [[String: AnyObject]] {
for place in pizzaPlaces {
if let name = place ["name"] as? String {
self.PizzaClass.append(name)
}
}
}
} catch {
print("Error Serializing JSON Data: \(error)")
}
print(self.PizzaClass)
}
}).resume()
You need to cast your NSJSONSerialization.JSONObjectWithData result as a [String:AnyObject].
let jsonObject = try NSJSONSerialization.JSONObjectWithData(returnedData, options: .MutableLeaves) as! [String: AnyObject]
Once you have that all you need to do is pay attention to what you're casting. Take the code below for an example. If we want to get our response object using jsonObject["response"] what kind of data structure do we have?
"response": {
"venues": [{
//... continues
}]
}
On the left we have "response" which is a string, on the right we have {} which is an AnyObject. So we have [String: AnyObject]. You just need to think about what object your dealing with piece by piece. Below is a working example that you can just paste into your application.
full working code:
func getJson() {
let request = NSMutableURLRequest(URL: NSURL(string: "https://api.foursquare.com/v2/venues/search?client_id=0F5M0EYOOFYLBXUOKTFKL5JBRZQHAQF4HEM1AG5FDX5ABRME&client_secret=FCEG5DWOASDDYII4U3AAO4DQL2O3TCN3NRZBKK01GFMVB21G&v=20130815%20&ll=29.5961,-104.2243&query=burritos")!)
let session = NSURLSession.sharedSession()
request.HTTPMethod = "GET"
request.addValue("application/json", forHTTPHeaderField: "Accept")
let task = session.dataTaskWithRequest(request) { (data: NSData?, response: NSURLResponse?, error: NSError?) -> Void in
guard let testResponse = response as? NSHTTPURLResponse else {
print("\(response)")
return
}
guard let status = HTTPStatusCodes(rawValue: testResponse.statusCode) else {
print("failed to unwrap status")
return
}
print(status)
switch status {
case .Created:
print("ehem")
case .BadRequest:
print("bad request")
case .Ok:
print("ok")
guard let returnedData = data else {
print("no data was returned")
break
}
do {
let jsonObject = try NSJSONSerialization.JSONObjectWithData(returnedData, options: .MutableLeaves) as! [String: AnyObject]
guard let response = jsonObject["response"] as? [String: AnyObject] else { return }
guard let venues = response["venues"] as? [AnyObject] else { return }
guard let location = venues[0]["location"] as? [String:AnyObject] else { return }
guard let formattedAddress = location["formattedAddress"] else { return }
print("response: \n\n \(response)\n------")
print("venues : \n\n \(venues)\n-------")
print("location : \n\n \(location)\n------")
print("formatted address : \n \(formattedAddress)")
} catch let error {
print(error)
}
// update user interface
dispatch_sync(dispatch_get_main_queue()) {
print("update your interface on the main thread")
}
}
}
task.resume()
}
place this either in its own file our outside of the class declaration,
enum HTTPStatusCodes : Int {
case Created = 202
case Ok = 200
case BadRequest = 404
}
Not that this was what you are looking for, but since you are new to Swift take a look at Alamofire. It handles JSON serialization for you. And when you need to chain calls PromiseKit is super slick.
Alamofire.request(.GET, url).responseJSON {response in
switch (response.result) {
case .Success(let value):
let pizzas = JSON(value).arrayValue
for place in pizzaPlaces {
if let name = place ["name"] as? String {
self.PizzaClass.append(name)
}
}
case .Failure(let error):
if let data = response.data, let dataString = String(data: data, encoding: NSUTF8StringEncoding) {
print("ERROR data: \(dataString)")
}
print("ERROR: \(error)")
}
}

Swift 2 Parsing JSON - Cannot subscript a value of type 'AnyObject'

I've tried following examples for parsing a JSON file (for example an answer to another question posted here: https://stackoverflow.com/a/27206145/4040201) but can't get it to work. I'm now getting the error "Cannot subscript a value of type 'AnyObject'" on the "let ... = item["..."] as? String" lines.
func connectionDidFinishLoading(connection: NSURLConnection) {
do {
let jsonResult = try NSJSONSerialization.JSONObjectWithData(self.bytes!, options: NSJSONReadingOptions.MutableContainers) as! Dictionary<String, AnyObject>
if let searchResults = jsonResult["Search"] as? [AnyObject] {
for item in searchResults {
let title = item["Title"] as? String //Error Here
let type = item["Type"] as? String //Error Here
let year = item["Year"] as? String //Error Here
print("Title: \(title) Type: \(type) Year: \(year)")
}
}
} catch let error as NSError {
NSLog("JSON Error: \(error)")
}
}
JSON Example:
{ "Search": [
{
"Title":"Example 1",
"Year":"2001",
"Type":"Type1"
},
{
"Title":"Example 2",
"Year":"2006",
"Type":"Type1"
},
{
"Title":"Example 3",
"Year":"1955",
"Type":"Type1"
}
]}
try this
func connectionDidFinishLoading(connection: NSURLConnection) {
do {
let jsonResult = try NSJSONSerialization.JSONObjectWithData(self.bytes!, options: NSJSONReadingOptions.MutableContainers) as! Dictionary<String, AnyObject>
if let searchResults = jsonResult["Search"] as? [[String: AnyObject]] {
for item in searchResults {
let title = item["Title"]
let type = item["Type"]
let year = item["Year"]
print("Title: \(title) Type: \(type) Year: \(year)")
}
}
} catch let error as NSError {
NSLog("JSON Error: \(error)")
}
}
You can do this
let title : String
if let titleVal = item["Title"] as? String
{
title = titleVal
print(title)
}
This will take care of checking whether the Title property value is null or not. If it is not null, It will read the value and set to titleVal variable.
If you are sure that it will never have a null value, you can use this code
let title = item["Title"] as! String

In Swift, check if a key exists in JSON

I have the following function. It is supposed to take the current song playing information from the API webpage. When a song is playing, the page says:
{ "artist" : "Artist", "song" : "Song" }
When no data is available (No song is playing):
{ "error" : "no song metadata provided" }
Is there a way to check if the "error" key exists? Or what can I do with this issue?
func songNowPlaying() {
let endpoint = NSURL(string: "http://api.vicradio.org/songs/current")
let jsonData = NSData(contentsOfURL: endpoint!)
do {
let parsed = try NSJSONSerialization.JSONObjectWithData(jsonData!, options: NSJSONReadingOptions.MutableContainers) as! NSMutableArray
SongNowText.text = parsed.valueForKey("song").componentsJoinedByString("")
ArtistNowText.text = parsed.valueForKey("artist").componentsJoinedByString("")
}
catch let error as NSError {
print("\(error)")
}
}
The URL returns a JSON dictionary not an array. You can check for both cases this way
func songNowPlaying() {
let endpoint = NSURL(string: "http://api.vicradio.org/songs/current")
if let jsonData = NSData(contentsOfURL: endpoint!) {
do {
let parsed = try NSJSONSerialization.JSONObjectWithData(jsonData, options: .MutableContainers) as! [String:String]
if let error = parsed["error"] {
print("Result error: \(error)")
} else {
if let song = parsed["song"] {
SongNowText.text = song
}
if let artist = parsed["artist"] {
ArtistNowText.text = artist
}
}
}
catch let error as NSError {
print("Serialization error: \(error)")
}
}
}
as the JSON object can be downcasted to [String:String] any further downcasting is not needed.