Reputation: 16414
I have some optional properties (a small sample of the actual properties in the class, for brevity):
var assigneeIds: [Int]?
var locationIds: [Int]?
var searchQuery: String?
I need to convert these to JSON. I've been advised by the maintainer of the API to not supply keys with nil values, so my toJson
method looks like this:
var result: [String: AnyObject] = [:]
if let assigneeIds = assigneeIds {
result["assignee_ids"] = assigneeIds
}
if let locationIds = locationIds {
result["location_ids"] = locationIds
}
if let searchQuery = searchQuery {
result["search_query"] = searchQuery
}
return result
This doesn't feel very "Swift" - it's quite verbose. Ideally, I'd like it to look similar to the following - with the exception of it not setting the key if the optional has no value. The below code will still set the key, along with an NSNull
value which gets serialised to "assignee_ids": null
in the resulting JSON. Presumably I can configure the serializer to omit NSNull
values, but I've encountered this pattern elsewhere and am interested to see if there's a better way.
return [
"assignee_ids" : self.assigneeIds ?? NSNull(),
"location_ids" : self.locationIds ?? NSNull(),
"search_query" : self.searchQuery ?? NSNull()
]
How can I skip creating key->NSNull
entries when building an inline dictionary in this way?
Upvotes: 1
Views: 319
Reputation: 4658
Try this:
return [
"assignee_ids" : self.assigneeIds ?? NSNull(),
"location_ids" : self.locationIds ?? NSNull(),
"search_query" : self.searchQuery ?? NSNull()
].filter { key, val -> Bool in !(val is NSNull) }
Upvotes: 2
Reputation: 14983
You actually don't need to unwrap the values at all, since the value won't be set in the dictionary when it's nil. Example:
var dict : [String : Any] = [:]
dict["a"] = 1 // dict = ["a" : 1]
dict["b"] = nil // dict = ["a" : 1]
dict["a"] = nil // dict = [:]
You can also CMD-Click on the bracket and look at the definition of the Dictionary subscript:
public subscript (key: Key) -> Value?
this means you get an Optional (whether it exists or not) and you set an Optional (to set it or remove it)
Your code will look like this:
var result: [String: AnyObject] = [:]
result["assignee_ids"] = assigneeIds
result["location_ids"] = locationIds
result["search_query"] = searchQuery
return result
Upvotes: 4