idiomatic way to unwrap many optional NSDictionary elements?

28 views
Skip to first unread message

Jean-Denis Muys

unread,
Jul 16, 2015, 9:56:18 AM7/16/15
to swift-l...@googlegroups.com
I have a dictionary coming from the parsing of a JSON (coming from an outside source). I want to store the values that are present in fixed properties, something similar to:

func feedJSONdata(jsonDict: NSDictionary) {
  var1 = jsonDict["var1"] as! String
  var2 = jsonDict["var2"] as! String
  var3 = jsonDict["var3"] as! String
  var4 = jsonDict["var4"] as! String
  var5 = jsonDict["var5"] as! String
 // and so on
}

Is there a way to guard against any of the entries in the dictionary to be missing?

Repeating:

if let var1Entry = jsonDict["var1"] as? String {
    var1 = var1Entry
}

seems heavy handed to me. Any lighter option?

Second, I may also want to guard against the dictionary entry being present but not a string.

Thanks,

Jean-Denis




Jens Alfke

unread,
Jul 16, 2015, 12:33:32 PM7/16/15
to Jean-Denis Muys, swift-l...@googlegroups.com

On Jul 16, 2015, at 6:56 AM, Jean-Denis Muys <jdm...@gmail.com> wrote:

Is there a way to guard against any of the entries in the dictionary to be missing?

Depends what you want the fallback behavior to be. It’s easy to fall back to a default value:

var1 = jsonDict["var1"] as? String ?? ""

If you want to skip assigning it at all, you can write a little helper function, called like
assignIfPresent(jsonDict, “var1”, &var1)

But yeah, binding between JSON and statically-typed languages can be a pain. The best implementation I’ve seen is Go’s  which is really simple and convenient — what you’re asking for would be a trivial one-liner in Go. But it takes advantage of reflection capabilities that Swift doesn’t have.

—Jens

Marco S Hyman

unread,
Jul 16, 2015, 1:43:54 PM7/16/15
to Jean-Denis Muys, swift-l...@googlegroups.com

> func feedJSONdata(jsonDict: NSDictionary) {
> var1 = jsonDict["var1"] as! String
> var2 = jsonDict["var2"] as! String
> var3 = jsonDict["var3"] as! String
> var4 = jsonDict["var4"] as! String
> var5 = jsonDict["var5"] as! String
> // and so on
> }

if let var1 = jsonDict["var1"] as? String where !var1.isEmpty,
let var2 = jsonDict["var2"] as? String where !var2.isEmpty,
let var3 = jsonDict["var3"] as? String where !var3.isEmpty,
let var4 = jsonDict["var4"] as? String where !var4.isEmpty,
let var5 = jsonDict["var5"] as? String where !var5.isEmpty {
// all vars are strings and not empty
// ...
} else {
// error
}

Marc





Marco S Hyman

unread,
Jul 17, 2015, 5:46:10 PM7/17/15
to Jean-Denis Muys, swift-l...@googlegroups.com
I wrote....
This works too and might be closer to what you want.

func feedJSONdata(jsonDict: NSDictionary) {

{
guard let var1 = jsonDict["var1"] as? String where !var1.isEmpty,
let var2 = jsonDict["var2"] as? String where !var2.isEmpty,
let var3 = jsonDict["var3"] as? String where !var3.isEmpty,
let var4 = jsonDict["var4"] as? String where !var4.isEmpty,
let var5 = jsonDict["var5"] as? String where !var5.isEmpty else {
print("Missing required variables")
return
}
print("vars are OK”)
// work with vars here
}

Bruno Berisso

unread,
Jul 29, 2015, 10:26:14 AM7/29/15
to Jean-Denis Muys, swift-l...@googlegroups.com
You can also do something like:

func feedJSONdata(jsonDict: NSDictionary) {

    //Get a dictionary with values of type String (filter non string and nil values)
    let dictWithCuratedValues = jsonDict.filter { ($1 is String) }
    
    //Check if the curated version has valid data (ex: dictWithCuratedValues.count > numberOfFileds, etc)
    ....
}

I'm not sure if 'filter' is available in Swift 2, but for prior version you will need to add some extra code to give Dictionary the ability to filter his elements:

extension Dictionary {
    init(_ pairs: [Element]) {
        self.init()
        for (k, v) in pairs {
            self[k] = v
        }
    }

    func filter(includeElement: Element -> Bool) -> [Key: Value] {
        return Dictionary(Swift.filter(self, includeElement))
    }
}

}

--
You received this message because you are subscribed to the Google Groups "Swift Language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to swift-languag...@googlegroups.com.
To post to this group, send email to swift-l...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/swift-language/18A98D4E-D659-4AFA-AE25-FD3C2E6062E9%40snafu.org.
For more options, visit https://groups.google.com/d/optout.

Reply all
Reply to author
Forward
0 new messages