I need to parse JSON file. Here is my getJSON func
public var shops: NSArray = []
public func getShop() {
let url = NSURL (string: "http://urltojson.com")
let data = NSData (contentsOfURL: url!)
shops = try! NSJSONSerialization.JSONObjectWithData(data!,options: .AllowFragments) as! NSArray
}
and here is how I get data from JSON
override func viewDidLoad() {
let test = shops ["Titile"] as? String
print(test)
}
The problem is when I run my code it shows me an error "Cannot convert value of type 'String' to expected argument type Int"
so, If I change ["Titile"] in let test = shops ["Titile"] for any Int, e.g. [8] let test = shops [8] as? String it works.
What did I do wrong?
looks like your variable "shops" is an array which takes an index as an integer instead of a dictionary which takes a key as a String.
//here shops is an array of strings
var shops:[String] = ["dog","cat","pig","cow"]
//shops[2] is equal to "pig"
//here shops is a dictionary of string keys and string values
var shops:[String:String] = ["animal1":"dog","animal2":"cat","animal3":"pig","animal4":"cow"]
//shops["animal2"] is equal to "cat"
Related
I am getting following JSON values in output:
[["category_title": Shelly], ["category_title": Thaddeus],
["category_title": Chantale], ["category_title": Adara],
["category_title": Mariko], ["category_title": Felicia]]
But I want it like below:
["Shelly","Thaddeus","Chantale", "Adara","Mariko","Felicia"]
I have the following Swift code. Please help me get above output.
func successGetTermsData(response: Any){
var UserRole : String = ""
var arrayOfDetails = response as? [[String: Any]] ?? []
UserRole = arrayOfDetails as? String ?? ""
print(arrayOfDetails)
}
You have to map the array of Dictionary arrayOfDetails to an array of String. flatMap ignores a missing key.
if let arrayOfDetails = response as? [[String: String]] {
let userRole = arrayOfDetails.flatMap { $0["category_title"] }
print(userRole)
}
There are many ways to do this. One way is to use flatmap to get just the values in your array of dictionaries:
let arrayOfValues = arrayOfDetails.flatMap { $0.values }
In order to get this to work, the names need to be inside double quotes: "Shelly", etc.
I am using Alamofire to get some JSON data and rather than having everything hardcoded, I was wondering how to simply include everything in the array.
Currently, this is the JSON file:
{"One":"Item1","Two":"Item2","Three":"Item3","Four":"Item4","Five":"Item5"}
My swift code:
var pickerData: [String] = [String]() //Array of content.
override func viewDidLoad() {
super.viewDidLoad()
Alamofire.request(.GET, "https://example.com/file.json").responseJSON{ (response) -> Void in
if let JSON = response.result.value{
let One = JSON["One"] as! String
let Two = JSON["Two"] as! String
let Three = JSON["Three"] as! String
let Four = JSON["Four"] as! String
let Five = JSON["Five"] as! String
self.mypickerview.delegate = self
self.mypickerview.dataSource = self
self.pickerData = [One, Two, Three, Four, Five]
...
How can I not make them hardcoded so that I can have my file like this and it would still work and include everything in the JSON, even if I add more in the future:
{"Item1","Item2","Item3","Item4","Item5","Item6"}
Aaron is right, your JSON should use an array to hold the item values.
But if you're stuck with this format, you can get the values in your pickerData like this:
if let JSON = response.result.value as? [String:AnyObject] {
let result = JSON.values.flatMap({ String($0) })
self.pickerData.appendContentsOf(result)
self.pickerData.sortInPlace()
}
pickerData is now:
["Item1", "Item2", "Item3", "Item4", "Item5"]
and items will be sorted in the picker array even if you add new ones later.
My PHP server-side returns a JSON like this:
[{"scan_status":"ok","visitorData":[{"visitorCompany":"xyl","visitorStreet":"street","visitorBranche":"health","visitorEmail":"wesweatyoushop#gmail.com","lastmodified":"2014-12-15 14:18:55"}]}]
Now in Swift I would like to store this data, and for this I am trying to parse the data into Swift variables, however I got stuck.
do {
//check wat we get back
let jsonData = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableLeaves )
let vData = jsonData[0]["visitorData"]
//let vCompany = vData["visitorCompany"]
print("Test vData: \(vData)")
}
This prints
Test vData: Optional(( { visitorStreet = street; visitorPhone = 01606478; visitorCompany = xyl; visitorBranche = Sports; visitorEmail = "health#gmail.com"; lastmodified = "2014-12-15 14:18:55"; } ))
but when I try to get visitorCompany with
let vCompany = vData["visitorCompany"]
I get a compile error:
Cannot subscript a value of type 'AnyObject?!' with an index of type 'String'
BTW, why do we see the equals sign in swift i.e. visitorStreet = street?
This is because the compiler doesn't know the type of your decoded objects.
Help the compiler using casting with if let:
do {
let jsonData = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableLeaves )
if let vData = jsonData[0]["visitorData"] as? [[String:AnyObject]] {
if let vCompany = vData[0]["visitorCompany"] {
print(vCompany)
}
}
}
let vData = jsonData[0]["visitorData"] populates vData with a generic AnyObject?, because Swift can't know what kind of objects PHP returns in the JSON.
You need to do a an optional cast to another dictionary before you can use vData like you want: jsonData[0]["visitorData"] as? [String:AnyObject].
And because a conditional cast returns an optional, it's best you do an optional binding to unwrap that optional, resulting in a code similar to this:
if let vData = jsonData[0]["visitorData"] as? [String:AnyObject] {
//let vCompany = vData["visitorCompany"]
print("Test vData: \(vData)")
}
Or even better, as jsonData can not be an array, or it could be an empty array (the server malfunctions and sends an invalid json for example), you can go even further with the validation:
if let items = jsonData as? [[String:AnyObject]], vData = items.first?["visitorData"] {
//let vCompany = vData["visitorCompany"]
print("Test vData: \(vData)")
}
items = jsonData as? [[String:AnyObject]] fails if jsonData is not an array, while vData = items.first?["visitorData"] fails if items.first is nil (optional chaining here), or if items.first doesn't have a visitorData key.
Try with this:
let vData = jsonData[0]["visitorData"]![0] as! [String:AnyObject]
I have successfully read the data from the following site: http://free.currencyconverterapi.com/api/v3/countries. I can see the values in the debug window. However, I am unable to iterate over the items. There are more than 200 items and I would like to iterate through them and print out their values (name, currency name, id, etc...)
The code to read the data:
func countryList() {
// Do any additional setup after loading the view.
let jsonUrl = "http://free.currencyconverterapi.com/api/v3/countries"
let session = NSURLSession.sharedSession()
let shotsUrl = NSURL(string: jsonUrl)
let task = session.dataTaskWithURL(shotsUrl!) {
(data, response, error) -> Void in
do {
let jsonData = try NSJSONSerialization.JSONObjectWithData(data!, options:NSJSONReadingOptions.MutableContainers ) as! NSDictionary
//let results: [String:[String:[String]]] = jsonData["results"]! as! [String : [String : [String]]]
let results = jsonData["results"]!
// iterate all items and print values
// how ???
} catch _ {
// Error
}
}
task.resume()
}
I have tried the following: let results : [String:[String:[String]]] = jsonData["results"]! however this does not work, and I would be surprised if it did :).
Any pointers?
using Xcode 7.1 and Swift 2
Result data returned with JSON (sample):
Country & Currency List{
"results":{
"GQ":{
"currencyId":"GQE",
"currencyName":"Central African CFA franc",
"name":"Equatorial Guinea",
"alpha3":"GNQ",
"id":"GQ"
},
"TD":{
"currencyId":"XAF",
"currencyName":"Central African CFA franc",
"name":"Chad",
"alpha3":"TCD",
"id":"TD"
}
.
.
.
The value of key results is a dictionary, it can be enumerated with a simple for .. in loop.
countrycode is the key, info the value.
Downcasting a dictionary to [String:AnyObject] includes all forms of nested objects.
This code prints out the country code and the name of each item
do {
let jsonData = try NSJSONSerialization.JSONObjectWithData(data!, options:NSJSONReadingOptions.MutableContainers ) as! [String:AnyObject]
let results = jsonData["results"] as! [String:AnyObject]
for (countryCode, info) in results {
print(countryCode, info["name"] as! String)
}
}
Be aware that there is no order because a dictionary is unordered by definition
I'm having a lot of difficulty with this one.
My server sends JSON arrays of dictionaries, with the dictionaries having a String as a key, with either a String or an Int as the value for the key. For example, if the key was name, it would return a string, but some values are asking for numeric things like "time since" which return Ints.
How do I handle this in Swift?
My first attempt was:
let dictArray = NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers, error: &jsonError) as Dictionary<String, Any>[]
But I get:
fatal error: can't unwrap Optional.none
If I change Any to AnyObject I can't cast it as an Int for some keys, it complains about the subscript.
What should I be doing?
The Cocoa to Swift binding maps id as AnyObject. And since the keys are not guaranteed to exist in the dictionary, the subscript returns AnyObject?.
Along those lines still seems to be problem with Xcode beta2.
For example, this crashes reproducibly the swift REPL:
let a : AnyObject? = nil
let b : Any? = a
So that might be the reason as well, why casting to Dictionary<String, Any>[] does not work.
Either way you might be better off using the "literal" mapping Dictionary<String, AnyObject>[] and checking the types yourself.
When casting AnyObject? to Int you have to remember that you are actually dealing with an optional. That means you have to unwrap it first using ! or an if let construct.
Alternatively you can just iterate over the dictionary:
var jsonError : NSError?
if var dictArray = NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers, error: &jsonError) as? Dictionary<String, AnyObject>[]
{
for dict in dictArray
{
for (key, data) in dict
{
var output : String = "(unknown)";
if let number = data as? Int
{
output = "\(number)"
}
else if let str = data as? String
{
output = str
}
println("\(key): \(output)")
}
}
}