Getting value from json response Swift - ios

[{
"_text" = "turn off the air con";
confidence = "0.609";
entities = {
"on_off" = (
{
value = off;
}
);
};
intent = "aircond_temperature";
}]
I have a json response named "outcomes", and I would like to extract the "off" value from "on_off".
So far what I've done is to get the first element from the response and then cast it to an NSDictionary which works fine, and then using object for key to get the values of each dictionary, and casting them to their respective types.
let firstOutcome:NSDictionary = outcomes.first as! NSDictionary
let intent:String = firstOutcome.objectForKey("intent") as! String
let entities:NSDictionary = firstOutcome.objectForKey("entities") as! NSDictionary
But when it comes to entities I have no idea what type should I cast "on_off" to. Any ideas?

your "on_off" key contain array of dictionaries, so you could try to access it by using this code.
let entities:NSDictionary = firstOutcome.objectForKey("entities") as! NSDictionary
let onOff = entities["on_off"] as! NSArray
let firstValue = onOff.firstObject as! NSDictionary
print(firstValue["value"])

The brackets tell the whole story. { is an object or dictionary, ( is an array. So, entities is a dictionary containing an array of dictionaries, where the inner dictionary has string keys and values.

Try this code:
let entities = entities["on_off"]
for var entity in entities {
print_r(entity["value"])
}

Related

I have and array inside the value of dictionary

I have an dictionary and the value containts the array of string as follows
arr = ["key":"["a","b","c","d","e","f","g"]"]
I want the new array to be like
let array = ["a","b","c","d","e","f","g"]
How to parse it
You can access dictionary items in few different ways, the easiest is:
let array = arr["key"]
You may need to conditionally unwrap it
if let array = arr["key"] as? [String] {
// rest of code with array
}

How to reform JSON in swift?

I am working on JSON in iOS swift,
I will query data from server as,
results = [{"type":"fruit", "name":"orange"},
{"type":"flower", "name":"rose"},
{"type":"fruit", "name":"apple"}]
I need to append above data to TableView based on the type, so that it will be displayed as shown below,
fruit
orange
apple
flower
rose
In order to display in TableView, the results should reform as,
updatedResult[String:[AnyObject]]() = {
"fruit":[{"name":"orange"},{"name":"apple"}],
"flower":[{"name":"rose"}]
}
How is it possible to reform the results to updatedResult using swift?
//Your example json
results = [{"type":"fruit", "name":"orange"},{"type":"flower","name":"rose"},{"type":"fruit", "name":"apple"}]
First you need to turn your json into an array of dictionaries to get the above object you think it will be:
if let results = try NSJSONSerialization.JSONObjectWithData(data,options: NSJSONReadingOptions.MutableContainers) as? [[String : AnyObject]]
{ //parse into form you want.}
// Your example desired result of dictionary with key:array of dictionaries
updatedResult[String:[AnyObject]]() = {"fruit":[{"name":"orange"},{"name":"apple"}],"flower":[{"name":"rose"}]}
Then you want to loop through the json result and grab out the values into the above format you want:
// Swift representation of your provided example
let results = [["type":"fruit", "name":"orange"],["type":"flower","name":"rose"],["type":"fruit", "name":"apple"]]
// Desired dictionary of key:array of dictionaries
var updatedResult = [String:[[String:String]]]()
for item in results {
if let name = item["name"], type = item["type"] {
if updatedResult.keys.contains(type) {
updatedResult[type]!.append(["name":name])
} else {
updatedResult[type] = [["name":name]]
}
}
}

How to cast Dictionary in Swift to related type?

This is what I am trying to do with the dictionary:
if let deliveries = dictionary["deliveries"] as? NSDictionary {
var castedDeliveries = [Double: Double]()
for delivery in deliveries {
if let value = delivery.value as? Double {
castedDeliveries[Double(delivery.key as! NSNumber)] = value //Could not cast value of type 'NSTaggedPointerString' (0x1a1e3af20) to 'NSNumber' (0x1a1e458b0).
}
}
settings!.deliveries = castedDeliveries
}
And this is what I try to cast, as a part of JSON response from server:
deliveries = {
2 = 0;
5 = "2.59";
7 = "3.59";
};
It doesnt work, because there is an error at commented line:
Could not cast value of type 'NSTaggedPointerString' (0x1a1e3af20) to 'NSNumber' (0x1a1e458b0).
You are trying to cast dictionary directly but instead you need to cast each key - value pair. If you want generic solution to this problem take a look at SwiftyJSON library which address JSON parsing problem for you.
Casting doens't mean data transformation from a type to another.
Your dictionary seems to be composed by Integer keys and String values.
If you want to transform in something else you ca use the map function.
let converted = deliveries.map{[Double($0) : Double($1)]}
But pay attention.
Here we are saying, iterate over the dictionary (in the $0 there is the dictionary key in the $1 there is the value) and create a new dictionary that has as a key a Double initialized at the key value and as a new value a Double initialized as the old dictionary value. The last conversion can fail, so the returned data is an optional.
As I noted in the comments, this isn't casting. You want a data conversion. You need to do that explicitly, especially in this case since it might fail.
Looking at the error, I think you really have a dictionary of [String:String] here (in NSDictionary form). That suggests the JSON is badly encoded, but such is life. Assuming that dictionary looks something like this:
let dictionary: NSDictionary = ["deliveries": ["2":"0", "5": "2.59", "7": "3.59"]]
You would convert it to [Double:Double] like this:
if let jsonDeliveries = dictionary["deliveries"] as? [String:String] {
var deliveries: [Double: Double] = [:]
for (key, value) in jsonDeliveries {
if let keyDouble = Double(key),
valueDouble = Double(value) {
deliveries[keyDouble] = valueDouble
}
}
// Use deliveries
}
This silently ignores any values that can't be converted to Double. If you would rather generate errors, use a guard let rather than an if let.

how to get Number value form dictionary

I am accessing data from JSON and storing it in dictionary 1 and passing this dictionary 1 to another view controller's dictionary 2. The view controller has all the details mainly 12 labels. I have managed to access the strings but i am not able to get the number values. Please have a look at the code.
DetailsViewController
var dict2 = [String : AnyObject]()
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.lblTopName.text = self.dict2["toponymName"] as? String
self.lblFcodeName.text = self.dict2["fcodeName"] as? String
self.lblName.text = self.dict2["name"] as? String
self.lblCountryCode.text = self.dict2["countrycode"] as? String
self.lblFCL.text = self.dict2["fcl"] as? String
self.lblFclName.text = self.dict2["fclName"] as? String
self.lblWikipedia.text = self.dict2["wikipedia"] as? String
self.lblFcode.text = self.dict2["fcode"] as? String
self.lblLongitude.text = self.dict2["lng"] as? String
Note. The last line of code that is longitude a number value. If I replace String with NSNumber it gives me the following error:
Cannot assign value of type NSNumber to type String
Forced cast should be avoided as much as possible, as it can lead to unexpected crashes. (self.dict2["lng"] as! NSNumber) will crash your application if for some reason the dictionary ends up without the lng key.
Your last line should be:
self.lblLongitude.text = self.dict2["lng"]?.description
This is guaranteed not to crash, as description exists on any object, and in case the dictionary somehow doesn't contain the "lng" key, you'll get a simple nil to assign to text.
plese try this if self.dict2["lng"] never null
self.lblLongitude.text = (self.dict2["lng"] as! NSNumber).stringValue
else if can be null then
self.lblLongitude.text = self.dict2["lng"]?.description
you can get integer value from dictionary like
int value = dict["integerValue"].integerValue // or doubleValue etc
and if you need string it can be like
self.lblLongitude.text = "\(self.dict2["lng"]. doubleValue)"
You can write like this
self.lblLongitude.text = String(format: "%f",self.dict2["lng"]!)

iOS 9 JSON Parsing loop

I'm creating an app that should retrieve some JSON from a database.
This is how my JSON looks:
[{"id":"1","longitude":"10","latitude":"10","visibility":"5","timestampAdded":"2015-10-01 15:01:39"},{"id":"2","longitude":"15","latitude":"15","visibility":"5","timestampAdded":"2015-10-01 15:06:25"}]
And this is the code i use:
if let jsonResult = JSON as? Array<Dictionary<String,String>> {
let longitudeValue = jsonResult[0]["longitude"]
let latitudeValue = jsonResult[0]["latitude"]
let visibilityValue = jsonResult[0]["visibility"]
print(longitudeValue!)
print(latitudeValue!)
print(visibilityValue!)
}
As you can see it only gets the first chunk from the JSON and if there are no JSON at all it will crash, but if i want it to count the amount and make an array out of it like this:
var longitudeArray = [10, 15]
var latitudeArray = [10, 15]
And so on...
I also need this to be apple watch compatible so i can't use SwiftyJSON.
What do i do? I really hope you can help me!
Thanks.
SOLVED!
Problems was solved by "Eric D."
This is the code:
do {
if let url = NSURL(string: "YOU URL HERE"),
let data = NSData(contentsOfURL: url),
let jsonResult = try NSJSONSerialization.JSONObjectWithData(data, options: []) as? [[String:AnyObject]] {
print(jsonResult)
let longitudeArray = jsonResult.flatMap { $0["longitude"] as? String }
let latitudeArray = jsonResult.flatMap { $0["latitude"] as? String }
print(longitudeArray)
print(latitudeArray)
}
} catch let error as NSError {
print(error.description)
}
Thank you soo much Eric!! :-)
You could use flatMap to get an array of your elements:
let longitudeArray = jsonResult.flatMap { $0["longitude"] as? String }
let latitudeArray = jsonResult.flatMap { $0["latitude"] as? String }
etc.
flatMap is like map but unwraps optionals, which is adequate because we need to safely cast the type of the object we get from each dictionary in the json array.
$0 represents the object in the current iteration of flatMap of the array it's applied to.
If you're currently using SwiftyJSON, then that would be:
let longitudeArray = jsonResult.flatMap { $1["longitude"].string }
let latitudeArray = jsonResult.flatMap { $1["latitude"].string }
because .string is SwiftyJSON's optional String value getter.
But as you said, you don't want to use it (anymore), so you need to use NSJSONSerialization to decode your JSON data, there's plenty of examples on the Web and on SO. Then you will be able to use my original answer.
You're already getting an array with all of the elements (not just the first one. you're simply only accessing the first one). jsonResult is an array of dictionaries. Each dictionary (in this case, based on the json you provided) contains these elements: id, longitude, latitude, visibility and timestampAdded. In order to access each of them, you can simply loop over jsonResult and access the i'th element (and not always the 0 element). This will also prevent the crash you're experiencing with the json is blank or invalid (since you'll only be going over the valid elements in jsonResult.
This will give you the flexibility to create the custom arrays you wish to create (in order to create an array of all of the longitudes, for example, you will simply add that element to the new array while looping over jsonResult). However, if you'd like to save yourself the trouble of manually building these arrays and assuming you have control over the json structure, I would recommend changing the received json to the relevant structure (a dictionary or arrays instead of an array of dictionaries), so it would better fit your needs and provide you the results in the relevant format right "out of the box".

Resources