I have a json file
I need to get the latest "id": "article" "createdAt": "2016-04-22T03:38:39.130Z" date. How do I go about getting this data from the request in swift?
Note: Sorry im a swift newb.
let url = "https://cdn.contentful.com/spaces/maz0qqmvcx21/entries?access_token=ae8163cb8390af28cd3d7e28aba405bac8284f9fe4375a605782170aef2b0b48";
var jsonData:NSData?
do{
jsonData = try NSData(contentsOfURL: NSURL(string: url)!, options: NSDataReadingOptions.DataReadingUncached)
let jsonObject:AnyObject? = try NSJSONSerialization.JSONObjectWithData(jsonData!, options: NSJSONReadingOptions.AllowFragments)
if let itemArray = jsonObject?.objectForKey("items") as? NSArray{
for item in itemArray{
if let sysItem = item.objectForKey("sys"){
//this is createdAt
if let createdAt = sysItem.objectForKey("createdAt") as? String{
print("createdAt:\(createdAt)")
}
if let contentTypeItem = sysItem.objectForKey("contentType")!.objectForKey("sys"){
//this is id
if let id = contentTypeItem.objectForKey("id") as? String{
print("id:\(id)")
}
}
}
}
}
}catch let err as NSError{
print("err:\(err)")
}
This code dosen't use any libraries,but you can use SwiftyJSON,this is will be easy to parse json.
Hope this help.
This can be done in simple way. I am assuming that you have parsed your json to dictionary
You have a key with items which is an array of dictionary and inside that dictionary you have createdAt and id(well it is deeper into the hierarchy but I will show you how to get it) keys. You can access it by simply doing this.
for dict in jsonDict["items"] as! Array<NSDictionary> {
let sysDict = dict["sys"] as! NSDictionary
print(sysDict["createdAt"]) //prints all createdAt in the array
let contentDict = sysDict["contentType"]
print((contentDict["sys"] as! NSDictionary)["id"]) // prints all ids
}
Hope this helps.
Related
Ok I have read so much about NSArray NSDictionary I'm lost now, what I want is to print the value 'name' from the first array item of my custom plist.
This is my plist:
and this is my code in my ViewController.swift:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let path = Bundle.main.path(forResource: "test", ofType: "plist")
let dic = NSArray(contentsOfFile: path!)
print(dic?.firstObject)
}
}
in my console I see:
Optional({
active = 0;
name = "John Doe";
})
I would think that print(dic?.firstObject["name"]) would do the trick
but I get an error: Value of type 'Any?' has no subscripts
So how do I print the values of name and active of my first array?
I know there are lots of answers on SO regarding this question, that's the reason I got so far.
but I just don't know how to fix this.
Kind regards,
Ralph
First of all please never use the NSArray/NSDictionary related API in Swift to read a property list. You are throwing away the type information.
However you can read the values with
let array = NSArray(contentsOfFile: path!) as! [[String:Any]]
for item in array {
let name = item["name"] as! String
let active = item["active"] as! Bool
print(name, active)
}
The dedicated and recommended API is PropertyListSerialization :
let url = Bundle.main.url(forResource: "test", withExtension: "plist")!
let data = try! Data(contentsOf: url)
let array = try! PropertyListSerialization.propertyList(from: data, format: nil) as! [[String:Any]]
A better way is the Codable protocol and PropertyListDecoder
struct User : Decodable {
let name : String
let active : Bool
}
override func viewDidLoad() {
super.viewDidLoad()
let url = Bundle.main.url(forResource: "test", withExtension: "plist")!
let data = try! Data(contentsOf: url)
let array = try! PropertyListDecoder().decode([User].self, from: data)
for item in array {
print(item.name, item.active)
}
}
The code must not crash. If it does you made a design mistake
To use subscripts you first need to cast the object returned by
dic?firstObject
to a dictionary, you can also unwrap the optional at this point.
if let item = dic?firstObject as? [String: Any] {
print(item["name")
}
I have a JSON file and I'm trying to access the array in it.
The JSON file looks like:
{
"cars": [{
"name": "BMW",
"icons": [["front.png", "back.png", "B3"],
["front_red", "back_red", "C4"]
]
}]
}
//cars is an array of dictionaries, I just mentioned one in the snippet.
I get the JSON data as:
func loadJSONData(){
if let path = Bundle.main.path(forResource: "testJSON", ofType: "json")
{
if let jsonData = NSData(contentsOfFile : path)
{
do {
if let jsonResult = try JSONSerialization.jsonObject(with: jsonData as Data, options: JSONSerialization.ReadingOptions.mutableContainers) as? [String:Any]
{
self.testJSONData = (jsonResult["cars"] as? Array)!
//self.testJSONData = (jsonResult["cars"] as? Array<Dictionary<String, Any>>)! //also tried this
}
}
catch let error as NSError {
print(error.localizedDescription)
}
}
}
}
testJSONData is declared as an array:
var testJSONData = [] as [Dictionary<String, Any>]
and the error occurs when trying to get the "icons" array from the JSON.
let namePredicate = NSPredicate(format: "name like BMW")
let filteredArray :Array = testJSONData.filter() { namePredicate.evaluate(with: $0) }
let carData: Dictionary = filteredArray[0] as Dictionary<String, Any>
let carIcons: Array = carData["icons"] as! Array //error at this line
Cannot convert value of type 'Array<_>' to specified type 'Array'
Can someone please show me where I'm doing wrong ? Thanks!
Array is a generic type in Swift, so when you want to declare an array variable, you always need to specific what type of elements the Array is holding. There's no such type as Array without specifying its Element type.
Also, there's no need for type annotations in Swift, the compiler can infer the types for you and you are explicitly telling the compiler the type by casting anyways.
carIcons should be of type Array<Array<String>> or as a shorthand [[String]]
let carIcons = carData["icons"] as! [[String]]
Some general comments about your code: don't use old Foundation types, such as NSData in Swift when they have native Swift equivalents. Also don't do force unwrapping of safe casted types, that makes no sense. Either handle the casting and unwrapping safely or simply force cast if you know the cast will succeed for sure. .mutableContainers have no effect in Swift, so don't use it. There's no need to cast error to NSError in a catch block, Swift has its own Error type.
func loadJSONData(){
if let fileURL = Bundle.main.url(forResource: "testJSON", withExtension: "json") {
do {
let jsonData = try Data(contentsOfFile: fileURL)
if let jsonResult = try JSONSerialization.jsonObject(with: jsonData) as? [String:Any], let cars = jsonResult["cars"] as? [[String:Any]] {
self.testJSONData = cars
} else {
print("Unexpected JSON format")
}
}
catch {
print(error)
}
}
}
However, if you are using Swift 4, the best solution would be using the type safe Codable protocol and JSONDecoder instead of JSONSerialization.
I am parsing json data in swift 3. this is the structure of the result.
I need to separate this brackected content and put them into a array.
(
{
name:"devin,patrick";
}
,
{
name:"devin,kalvin";
}
,
{
name: "devin,nic";
}
)
This is the code,
//parsing json data
if let jsonparsed = content as? NSDictionary {
if let neededData = jsonparsed["data"] {
print(neededData)
let exactData = String(describing:neededData)
let gotData = exactData.components(separatedBy: ",")
}
}
I converted data to a string and tried to separate content by comma, it wont work because name also having commas, I need to separate content that covered by comma, Any help would be great.
After serializing your json string, get a list of Dictionary, get the name of each dictionary and then do the componentsSeparatedBy yo get every name
if let data = text.data(using: .utf8) ,
let dict = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: String]{
let array = dict.flatMap({$0["name"]}) //return ["devin,patrick", "devin,kalvin", "devin,nic"]
let names = array.flatMap({$0.components(separatedBy: ",")}) //return ["devin" ,"patrick" ,"devin" ,"kalvin" ,"devin" ,"nic"]
let uniqueNames = Set(names) // return ["nic", "patrick", "devin", "kalvin"]
}
I have two variable called "Countries" and "Places" and I'm trying to read a Data.plist and retrieve some values
This is the Data.plist:
Data.plist
I can't read the plist from the variables.
Let use as an example, the value of Countries is "Italia" and the value of Places is "Naples", how can I retrieve the two different values written in "Item 0" and "Item 1".
I've been searching for days in internet some tutorial who could help me but I couldn't make any of these working for my case (I used more tutorial examples but due my low reputation I can't post more than 2 links).
I tried to follow these tutorial:
Swift - searching through dictionaries in an array in a plist
http://sweettutos.com/2015/06/03/swift-how-to-read-and-write-into-plist-files/
I tried, for example, to use this code without use the "variables", but even this is not working:
let path = NSBundle.mainBundle().pathForResource("Dati", ofType: "plist")
let dict = NSDictionary(contentsOfFile: path!)
let value: AnyObject = (dict!.objectForKey("Italia")!.objectForKey("Naples")?.objectForKey("Item 0"))!
Can you please help me on this?
Thanks in advance.
This is a pure Swift solution using only Swift native types:
if let url = NSBundle.mainBundle().URLForResource("Dati", withExtension: "plist"), data = NSData(contentsOfURL: url) {
do {
let dictionary = try NSPropertyListSerialization.propertyListWithData(data, options: [], format: nil) as! [String:AnyObject]
if let city = dictionary["Italia"]?["Naples"] as? [AnyObject] {
let item0 = city[0] as! Int
let item1 = city[1] as! String
} else {
print("Italia or Naples doesn't exist")
}
} catch let error as NSError {
print("Property List Serialization Error: \(error)")
}
} else {
fatalError("File couldn't be read")
}
If you change the plist file to use only String values you can avoid some type casting
if let url = NSBundle.mainBundle().URLForResource("Dati", withExtension: "plist"), data = NSData(contentsOfURL: url) {
do {
let dictionary = try NSPropertyListSerialization.propertyListWithData(data, options: [], format: nil) as! [String:[String:[String]]]
if let city = dictionary["Italia"]?["Naples"] {
let item0 = city[0]
let item1 = city[1]
} else {
print("Italia or Naples doesn't exist")
}
} catch let error as NSError {
print("Property List Serialization Error: \(error)")
}
} else {
fatalError("File couldn't be read")
}
I have been reading some of the responses to questions with similar problems but I just can't figure it out...
I have PostService that does a JSON POST request and fetches the data from a MySQL database. Everything was working before I did the conversion to Swift 2.0 and now it's giving me gears. (Code comes from Skip Wilson's Youtube series - Swift: Using External Databases and API's)
It gives the above error in the output and stops and highlights this line -
"let response = (try! NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers)) as! NSDictionary"
var settings:Settings!
init() {
self.settings = Settings()
}
let userLoginEmail = "admin#email.co.za";
let userLoginPassword = "1234";
func getPosts(callback:(NSDictionary) -> ()) {
request(settings.viewPosts, callback: callback)
}
func request(url:String, callback:(NSDictionary) -> ()) {
let myURL = NSURL(string: url)
let requested = NSMutableURLRequest(URL:myURL!);
requested.HTTPMethod = "POST";
let postString = "email=\(userLoginEmail)&password=\(userLoginPassword)";
print("email=\(userLoginEmail)&password=\(userLoginPassword)")
requested.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding);
let task = NSURLSession.sharedSession().dataTaskWithRequest(requested) {
(data, response, error) in
let response = (try! NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers)) as! NSDictionary
callback(response)
}
task.resume()
}
Here's my JSON post... With my limited knowledge and reading up on json.org, it looks like an object with an array inside it containing a bunch of objects (A dictionary?) The format of all of this did not change and my app would fetch the data from the database and display it correctly before the conversion..
{"posts":[{"Post":{"Id":"5","idno":"4","product":"Aspen Simvastatin","quantity":"30","due_date":"2015-04-11","last_repeat":"2015-04-10","doctor":"Dr. Jim Jones","store":"Central","currentrepeat":"2","totalrepeat":"6","active_ingredient":"Simvastatin","strength":"20mg","manufacturer":"Aspen Pharmacare","dosage_form":"Tabs","directions":"Take one tablet daily","repeatflag":"0","repeattimestamp":"2015-08-17 20:38:13"}},{"Post":{"Id":"6","idno":"4","product":"Mybulen","quantity":"45","due_date":"2015-04-11","last_repeat":"2015-04-10","doctor":"Dr. Jim Jones","store":"Central","currentrepeat":"3","totalrepeat":"6","active_ingredient":"Codeine Phosphate;Ibuprofen;Paracetamol","strength":"10mg;200mg;250mg","manufacturer":"Aspen Pharmacare","dosage_form":"Tabs","directions":"Take one or two tablets four times a day after meals","repeatflag":"0","repeattimestamp":"2015-08-17 20:38:13"}},{"Post":{"Id":"7","idno":"4","product":"Ecotrin XL","quantity":"30","due_date":"2015-04-11","last_repeat":"2015-03-11","doctor":"Dr. Jim Jones","store":"Central","currentrepeat":"4","totalrepeat":"6","active_ingredient":"Aspirin","strength":"81mg","manufacturer":"Litha Pharma","dosage_form":"Tabs","directions":"Take one tablet in the morning","repeatflag":"0","repeattimestamp":"2015-08-17 20:38:13"}},{"Post":{"Id":"8","idno":"4","product":"Lorien","quantity":"28","due_date":"2015-04-11","last_repeat":"2015-03-11","doctor":"Dr. J. Eckel","store":"Central","currentrepeat":"4","totalrepeat":"6","active_ingredient":"Fluoxetine HCl","strength":"20mg","manufacturer":"Aspen Pharmacare","dosage_form":"Caps","directions":"Take one capsule in the morning","repeatflag":"0","repeattimestamp":"2015-08-17 20:38:13"}}]}
I would be extremely grateful for any help on this.
In my masterViewController's viewDidLoad(), I have this code which process the information fetched...
service = PostService()
service.getPosts {
(response) in
self.loadPosts(response["posts"]! as! NSArray)
}
}
func loadPosts(posts:NSArray) {
for post in posts {
let post = post["Post"]! as! NSDictionary
let Id = Int((post["Id"]! as! String))!
let idno = Int((post["idno"]! as! String))!
let product = post["product"]! as! String
let quantity = Int((post["quantity"]! as! String))!
let doctor = post["doctor"]! as! String
let store = post["store"]! as! String
let currentrepeat = Int((post["currentrepeat"]! as! String))!
let totalrepeat = Int((post["totalrepeat"]! as! String))!
let active_ingredient = post["active_ingredient"]! as! String
let strength = post["strength"]! as! String
let manufacturer = post["manufacturer"]! as! String
let dosage_form = post["dosage_form"]! as! String
let directions = post["directions"]! as! String
let postObj = Post(Id: Id, idno: idno, product: product, quantity: quantity, doctor: doctor, store: store, currentrepeat: currentrepeat, totalrepeat: totalrepeat, active_ingredient: active_ingredient, strength: strength, manufacturer: manufacturer, dosage_form: dosage_form, directions: directions)
postsCollection.append(postObj)
dispatch_async(dispatch_get_main_queue()) {
self.tableView.reloadData()
}
}
You are telling NSJSONSerialization that you are absolutely sure that the JSON can be parsed and that you want your app to crash if it doesn't. (That's the try! ). Well, there are plenty of situations where you are asking for JSON and you are getting html back, so your users won't be happy with that, let's say if they use your app in a hotel or at the nearest starbucks.
Next, you are telling NSJSONSerialization that you are absolutely sure that the JSON contains a dictionary, and that you want your app to crash if it doesn't (as! NSDictionary). Guess what, you were given an array. You better read the documentation for your API, and check what you are given here.
BTW. I don't care what you are posting what JSON you are supposedly getting - I know that you received an array. Don't believe it? First rule of debugging: What you know is wrong.