How to get json data from nested dictionary in swift - ios

How can I access data from a nested dictionary - when I want to save all data from "CourseDates”? CourseDates = NSArrayM
let json = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.AllowFragments)
if let test = json[0]["CourseDates"] as? [[String : AnyObject]] {
// heres my problem
}

You can create a function that returns NSDictionary like this:
func parseJSON(data: NSData) -> NSDictionary{
var dic: NSDictionary!
do {
boardsDictionary = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers) as! NSDictionary
} catch let error as NSError {
print(error.localizedDescription)
print("Error could not parse JSON data, it's null maybe?!!")
}
//'\(jsonStr)'
return dic
}
UPDATE:
Add This:
public class func jsonToNSData(json: AnyObject) -> NSData?{
return NSJSONSerialization.dataWithJSONObject(json, options: .allZeros, error: nil)
}
let dic = parseJSON(jsonToNSData(YourJsonData)) as! NSDictionary

Hi you can try SwiftyJson, It is a great source through which you can deal with complex JSON in a much more simpler way then you ever thought. For example
{
"metadata":{
"responseInfo":{
"status":200,
"developerMessage":"OK",
}
},
"results":[
{
"title":"Legal immigrants should get freedom before undocumented immigrants – moral, just and fair",
"body":"I am petitioning President Obama's Administration to take a humane view of the plight of legal immigrants. Specifically, legal immigrants in Employment Based (EB) category. I believe, such immigrants were short changed in the recently announced reforms via Executive Action (EA), which was otherwise long due and a welcome announcement.",
"issues":[
{
"id":"28",
"name":"Human Rights"
},
{
"id":"29",
"name":"Immigration"
}
],
"signatureThreshold":100000,
"signatureCount":267,
"signaturesNeeded":99733,
},
{
"title":"National database for police shootings.",
"body":"There is no reliable national data on how many people are shot by police officers each year. In signing this petition, I am urging the President to bring an end to this absence of visibility by creating a federally controlled, publicly accessible database of officer-involved shootings.",
"issues":[
{
"id":"28",
"name":"Human Rights"
}
],
"signatureThreshold":100000,
"signatureCount":17453,
"signaturesNeeded":82547,
}
]
}
From this JSON if you want to extract the result you can do easily like this
func parseJSON(json: JSON) {
for result in json["results"].arrayValue {
let title = result["title"].stringValue
let body = result["body"].stringValue
let sigs = result["signatureCount"].stringValue
let obj = ["title": title, "body": body, "sigs": sigs]
objects.append(obj)
}
}

Here is the simple example how can we extract data from the NSDictionary. And this is simple and i'm not following any standards...
I considered json data in String format.
var data = "{\"data\":{\"fName\":\"naveen\",\"lName\":\"kumar\"},\"friend\":[{\"name\":\"manju\",\"male\":true},{\"name\":\"tanuja\",\"male\":false}]}"
After that you can do
var nsdata = data.dataUsingEncoding(NSUTF16StringEncoding)
if let json = try? NSJSONSerialization.JSONObjectWithData(nsdata!, options: .MutableContainers) as! NSDictionary {
if let some = json["friend"]![0]["name"]! {
print(some) // prints -- manju
}
}
By using the subscipt we can get the data.

Related

Creating Custom JSON Mapper in Swift

Here performing two tasks :
1. Convert Dictionary to Model Object
2. Convert Model object to Dictionary
Wrote down following codes and its working perfectly :
JsonMapper.Swift
class JsonMapper
{
/**
*#Method : decodeUser
*#Param : Dictionary of type [String:Any]
*#ReturnType : User ( which is model )
*#Description: Responsible for mapping Dictionary to Model object
*/
func decodeUser(userDict:[String:Any]) -> User?
{
let decoder = JSONDecoder()
var objUser: User?
do {
let jsonData = try JSONSerialization.data(withJSONObject: userDict, options: JSONSerialization.WritingOptions.prettyPrinted)
objUser = try decoder.decode(User.self, from: jsonData)
print("✅ User Object: \n",objUser)
} catch {
print("❌ Error",error)
}
return objUser ?? User(id: "", type: “”,salary:””)
}
/**
*#Method : encodeUser
*#Param : User
*#ReturnType : Dictionary of type [String:Any]
*#Description: Responsible for mapping Model object User to Dictionary
*/
func encodeUser(modelObj:User) -> [String:Any]
{
let encoder = JSONEncoder()
var objProfileDict = [String:Any]()
do {
let data = try encoder.encode(modelObj)
objUserDict = (try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any])!
print("✅ json dictionary: \n",objProfileDict)
}
catch {
print("❌ Error \(error)")
}
return objUserDict
}
}
User Model :
struct User:Codable
{
let id : String
let type : String
let salary : String
}
Above code works perfectly fine, no problem.
Now the issue is :
1. Everytime i need to convert Dictionary into any model , here you can see Model User is fixed so i want to convert above code in generic model so that , i will pass any model and then it return me the result.
When i pass Dictionary it should return me the model which i will specify during run time , i want to make this generic for every model , so that Dictionary could be convert into any of specified model.
Kindly provide your valuable inputs.
**Note :
1.Dont want to use any 3rd party lib like ObjectMapper , etc.
The name JsonMapper is misleading here. What you really mean is a dictionary mapper. Your approach is fine. If you want it to be generic, just pass the type. I'd probably do it this way:
extension JSONDecoder {
/**
*#Method : decodeUser
*#Param : Dictionary of type [String:Any]
*#ReturnType : User ( which is model )
*#Description: Responsible for mapping Dictionary to Model object
*/
func decode<T: Decodable>(_ type: T.Type, from dictionary: [String: Any]) throws -> T
{
let jsonData = try JSONSerialization.data(withJSONObject: dictionary)
return try decode(T.self, from: jsonData)
}
}
And similarly for JSONEncoder.

Swift 3 retrieve value from nested JSON Array

Hi I am currently learning Swift 3, and I have an app I am "developing" to provide weather for a specific location.
I have got my MetOffice API and retrieved the JSON required. I am able to retrieve the location without issue, but when I try to get the temp data I get no result. The temp data is listed as DM in the JSON and is an array within an array within a dictionary within dictionary.
my current code looks like
if let SiteRep = dict["SiteRep"] as? Dictionary<String, Any> {
if let DV = SiteRep["DV"] as? Dictionary<String,Any> {
if let location = DV["Location"] as? Dictionary<String, Any> {
if let period = location["Period"] as? Dictionary<String, Any> {
if let Rep = period["Rep"] as? [Dictionary<String, Any>] {
if let DM = Rep[0]["DM"] as? Double {
self._currentTemp = DM
} } } } } }
relevant vars are declared above this.
I'm not sure how to correct this code to pull this required value back from the JSON
Json as follows, the value i am trying to retrieve is highlighted in bold
{
"SiteRep":{
"Wx":{ },
"DV":{
"dataDate":"2017-02-10T12:00:00Z",
"type":"Forecast",
"Location":{
"i":"350497",
"lat":"99.6115",
"lon":"-21.0017",
"name":"TOWN",
"country":"ENGLAND",
"continent":"EUROPE",
"elevation":"160.0",
"Period":[
{
"type":"Day",
"value":"2017-02-10Z",
"Rep":[
{
"D":"NE",
"Gn":"16",
"Hn":"77",
"PPd":"51",
"S":"9",
"V":"GO",
**"Dm":"2",**
"FDm":"-2",
"W":"24",
"U":"1",
"$":"Day"
},
{
"D":"NNW",
"Gm":"20",
"Hm":"89",
"PPn":"58",
"S":"11",
"V":"GO",
"Nm":"-1",
"FNm":"-6",
"W":"24",
"$":"Night"
}

Loop through JSON and store in Coredata in swift 3 using Alamofire

I'm beginner in IOS developer. I getting the JSON from URL by using Alamofire. I trying to Loop through JSON for store in Coredata.
JSON:
[{
"stocks": [
{
"growth": "29.87",
"stock_name": "BLA"
},
{
"growth": "28.87",
"stock_name": "ADVANC"
}
],
"template_name": "stock growth more than 20 in 90 day"
} , ........
]
My code
var arrRes = [[String:AnyObject]]()
func loadJSONTemplate() {
Alamofire.request("http://1xx.xxx.xxx.xx/").responseJSON { response in
print(response.result)
if((response.result.value) != nil) {
if let data = response.result.value {
self.arrRes = data as! [[String:AnyObject]]
}
}
for i in 0 ..< self.arrRes.count {
var a = self.arrRes[i]
let templatename = a["template_name"] as? String
let teststock = a["stock_name"] as? String
print(teststock)
}
In coredata, "template_name" has value but, "stock_name" and "growth" is nil
I don't understand. Please tell me how to solve this. Thank you
You're trying to access data from another level of the json.
So template_name and stocks are peers, but stock_name and growth are in objects which make up the children of stocks.
You need to do something like
let templatename = a["template_name"] as? String
let stockArr = a["stocks"] as? Array
for stock in stockArr {
let stockName = stock["stock_name"]
let growth = stock["growth"]
}
I would encourage you, once you feel more comfortable, to check out ObjectMapper through Cocoapods. A little on the advance side, but make life a lot easier.

Swift--Reading in JSON file

Using Xcode 6.4 and programming in swift.
I am typing a program that should read in JSON from a URL. A sample of the JSON can be found at this URL (https://itunes.apple.com/us/rss/topmovies/limit=2/json) and Ive been using this site to parse the JSON in order to read it better (http://json.parser.online.fr/).
Now I need to work through the levels of the JSON in order to get to
the actual movie names and image URL's but I am lost at what kind of variable entryDictionary should be. I was thinking it should be an array of dictionaries, and this compiles, but the output of entryDictionary in the console is sloppy looking, starting with Optionl( and not entry{ as it should. And when I go to loop through entryDictionary, I get an error saying entry does not have a subscript of type AnyObject.
So I am asking how I retrieve the im:name fields and im:image from the JSON.
func downloadDataFromURLString(urlString: String) {
//Downloaded data and is now stored in data. Took code out because
//irrelevant to my problem at this point. Data variable has correct
//JSON, now I am trying to parse it.
} else { //download suceeded, time to parse
var error: NSError? = nil
var names = [String]()
if let rootDictionary = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: &error) as? [String: AnyObject] {
let feedDictionary = rootDictionary["feed"] as! [String: AnyObject]
let entryDictionary: AnyObject? = feedDictionary["entry"]
println(entryDictionary) //For debugging
//for entry in entryDictionary as! NSArray {
// let name = entryDictionary["name"]
// let image = entryDictionary["image"]
// let movie = Movie(name: name!, image: image!)
// weakSelf!.movies.append(movie)
//}
here is a blueprint of the JSON
"feed":{
"author":{},
"entry":[
{
"im:name":{
"label":"Deadpool"
},
"im:image":[],
"summary":{},
"im:price":{},
"im:contentType":{},
"rights":{},
"title":{},
"link":[],
"id":{},
"im:artist":{},
"category":{},
"im:releaseDate":{}
AnyObject is indeed not subscriptable (you're trying to subscript a variable whose type is AnyObject? with ["feed"]). You should also avoid casting to Cocoa container types like NSArray and NSDictionary whenever you can. Here's an example of how you might get the labels out of the entries array's names array:
import Foundation
func labels(feedDictionary:[String:AnyObject]) -> [String] {
guard let entries = feedDictionary["entry"] as? [String:AnyObject] else {
return []
}
return entries.flatMap { (key:String, value:AnyObject) -> String? in
guard key == "im:name" else {
return nil
}
guard let name = value as? [String:String] else {
return nil
}
return name["label"]
}
}
I'd however advise against using NSJSONSerialization on its own in Swift for anything but the simplest case, as you end up casting and wrapping optionals until the cows come home.
There are good 3rd party libraries such as Freddy and SwiftyJSON which apply Swift language features to accomplish a very convenient JSON (de)serialization experience.
For instance with Freddy you could express your problem in the following style:
let json = try JSON(data: data)
json.decode("feed", type:Feed.self)
struct Feed: JSONDecodable {
let entries:[Entry]
init(json: JSON) throws {
self.entries = try json.arrayOf("entry", type:Entry.self)
}
}
struct Entry:JSONDecodable {
let name:IMName
init(json: JSON) throws {
self.name = try json.decode("im:name", type:IMName.self)
}
}
struct IMName:JSONDecodable {
let label:String
init(json: JSON) throws {
self.label = try json.string("label")
}
}

Accessing devices data from Facebook graph Api request in swift

I have made a graph request using the FBSDK in my swift application for iphone and I am having some difficulty accessing some of the information it has returned in the result. Specifically I want to get the list of device platforms the user uses. Playing around with the Graph api explorer I get this data for a query on a user's devices.
{
"devices": [
{
"os": "iOS"
}
],
"id": "12345678912345"
}
but in swift the data returned is in this format when I print the graph results value to console:
{
devices = (
{
os = iOS;
}
);
}
so my question is, how do I get the value of 'os' in swift? all my attempts casting the data to NSDictionaries and NSArrays etc have all failed.
let listOfDevices: String = result.valueForKey("devices") as? String
outputs
devices = (
{
os = iOS;
}
);
which just goes to show it doesn't contain any key/pair values for an NSDictionary when I search for ["os"] because of those"()" parenthesis. All help appreciated. Probably something really simple...
I don't want to use string regex.
listOfDevices should be a dictionary.
Swift 2
do {
// Replicating your data for the example
let response = "{\"devices\": [{\"os\": \"iOS\"}],\"id\": \"12345678912345\"}"
// Cast the response as a Dictionary with String as key and AnyObject as value
if let data = response.dataUsingEncoding(NSUTF8StringEncoding),
listOfDevices = try NSJSONSerialization.JSONObjectWithData(data, options: []) as? [String:AnyObject] {
// Value of `devices` is an array of dictionaries
if let devices = listOfDevices["devices"] as? [[String:AnyObject]] {
for device in devices {
if let os = device["os"] as? String {
print(os)
}
}
}
// Value of `id` is a String
if let id = listOfDevices["id"] as? String {
// use `id`
}
}
} catch let error as NSError {
print(error.localizedDescription)
}
Swift 1
// Replicating your data for the example
let response = "{\"devices\": [{\"os\": \"iOS\"}],\"id\": \"12345678912345\"}"
let data = response.dataUsingEncoding(NSUTF8StringEncoding)
// Cast the response as a Dictionary with String as key and AnyObject as value
let listOfDevices = NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers, error: nil) as! [String:AnyObject]
// Value of `devices` is an array of dictionaries
if let devices = listOfDevices["devices"] as? [[String:AnyObject]] {
for device in devices {
if let os = device["os"] as? String {
println(os)
}
}
}
// Value of `id` is a String
if let id = listOfDevices["id"] as? String {
// use `id`
}

Resources