I am filling a dict with values from json:
var dict = Dictionary<String, AnyObject>()
dict["venue"] = json["info"]["venue"].string!
dict["addressStreet"] = json["info"]["addressStreet"].string!
dict["capacity"] = json["info"]["capacity"].int!
dict["mascot"] = json["info"]["mascot"].string!
dict["foodService"] = json["info"]["foodService"].boolean!
Imagine the values from the json are:
//Smith Concert Hall (a string)
//1234 Main Street (a string)
//150 (a number)
//no mascot listed - a null value
//true for food service - a boolean value
In case it has a bearing on this question, I am using SwiftyJSON to access the items in json. Info on SwiftyJSON is here: https://github.com/SwiftyJSON/SwiftyJSON
So, in this example we are dealing with several different types, such as strings, ints, booleans, and the chance of null values.
The json I am working on doesn't just have 5 items like in the above example. It has many. So, for an efficient program, I have done the following:
for (indexCount, element) in enumerate(appDelegate.json["info"]){
dict[element.0] = json["info"][element.0]
}
Which means instead of creating specific assignment statements for all possibilities, I am looping through and creating a tuple from each json item. The tuple contains the key and value. With that key and value I am automatically setting the key and value of the dict items.
BUT - when I go to use the dict item later, there is a problem. For example, if I try to do this, I get nil:
let a = dict["capacity"] as? String
println(a) //results with: nil
let b = dict["capacity"]
println("\(b)") //results with: nil
let c = String(stringInterpolationSegment: dict["capacity"])
println(c) //results with: nil
So to recap: If I am filling an "String, AnyObject" dictionary by enumerating through a json array with different value types... what can I do on the front or back end of this process to avoid errors and have useful data? In particular, strings seem to work fine, but when I encounter an int and try to cast it as a string (I have tried several ways) it fails all together or returns nil.
Thank you.
The data held in a JSON
object can be String
, Bool
, NSNumber
, NSURL
, ... and you are using only String
, Int
and Bool
. The common supertype of these is Any
. Declare your dict
as Dictionary<String,Any>
. (Every where you subsequently use your Any
data you will be forced to type-cast to String
, Bool
, Int
as appropriate for the 'tag')
But, I'd say, by using Any
you are fighting the types. Swift is a strongly-typed, statically-typed programming language and you need to go with it by being explicit with your types. Get your generic input data, from JSON, into explicitly-typed abstractions, manipulate those abstractions, and then, if required, convert back to generic output data, to JSON.
class Event {
var venue : String
var addressStreet : String
var capacity : Int
var mascot : String
var foodService : Bool
// ... many more ...
init (json:JSON) {
self.venue = json["venue"].string!
...
}
}
var event1 = Event(json["info"])
Of course, the above only works if the JSON
data tags are static. If, rather, there really is no static structure to the data, then Dictionary<String,Any>
is the best you can do and you'll need to deal with Any
.
It turns out, when looping through JSON to add the items to a dictionary, you don't need to worry about their type. You can just add them just as they are: unchanged in their 'JSON' type to the array.
This question began with a loop through JSON results to add them to a dictionary:
var dict = Dictionary<String, AnyObject>()
for (indexCount, element) in enumerate(appDelegate.json["info"]){
dict[element.0] = json["info"][element.0]
}
Now I see that the problem was that the array was defined as 'String, AnyObject'. But it turns out if we declare the array as:
var dict = Dictionary<String, JSON>()
(we changed AnyObject to JSON)...then we are able to add and retrieve the original JSON value. Then when we are about to use the value somewhere (such as putting string into a label, or getting an int to do a calculation) SwiftyJSON allows us to cast it with a subscript such as .string or .int.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.