5
\$\begingroup\$

Here's a quick extension for [String: AnyObject] dictionaries in Swift. The output needs to be in the following format (order and spacing don't matter):

{"key": "val", "keywdict": {"anotherKey": 100, "Key2": "Val2"}, "strings": ["string", "another"]}

I am wondering if there's a better way, or if this can be improved.

extension Dictionary //...
func toJSONString() -> String {
 var pcs = [String]()
 for (key, val) in self {
 var valStr = ""
 if let val = val as? String {
 valStr = "\"\(val)\""
 } else if let val = val as? Dictionary<String, AnyObject> {
 valStr = val.toJSONString() // recursion for nested dictionaries
 } else if let val = val as? Array<String> {
 let tmpStr = "\",\"".join(val)
 valStr = "[\"\(tmpStr)\"]"
 } else if let val = val as? NSNumber {
 valStr = "\(val)"
 }
 pcs.append("\"\(key)\":\(valStr)")
 }
 return "{" + ",".join(pcs) + "}"
}
Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Apr 17, 2015 at 16:01
\$\endgroup\$
1
  • 1
    \$\begingroup\$ Welcome to CodeReview, Andrew. I hope you get some fine answers. \$\endgroup\$ Commented Apr 17, 2015 at 16:27

1 Answer 1

5
\$\begingroup\$

Your dictionary to JSON converter has some serious issues:

  • The special characters " and \in strings are not properly escaped:

    [ "a\"b" : "c\\d"].toJSONString()
    

    produces "{"a"b":"c\d"}", correct would be {"a\"b":"c\\d"} (see for example http://json.org).

  • Only arrays of strings are implemented, but not arrays of numbers or arrays of arrays or dictionaries.
  • Value types which are not covered by your code just print as an empty string instead of causing an error.
  • Boolean values are simply treated as numbers:

    [ "key" : true].toJSONString()
    

    gives {"key":1}, correct would be {"key":true}

While this could all be fixed, it probably isn't worth the effort because there is a Foundation class NSJSONSerialization which already does exactly this:

var dict : [String: AnyObject] = [:]
dict["a\"b"] = "c\\d"
dict["strings"] = ["string", "another"]
dict["keywdict"] = [ "anotherKey": 100, "Key2": "Val2"]
dict["numbers"] = [ 1, 2, 3]
dict["bools"] = [ true, false]
var error : NSError?
if let jsonData = NSJSONSerialization.dataWithJSONObject(dict, options: nil, error: &error) {
 let jsonString = NSString(data: jsonData, encoding: NSUTF8StringEncoding)! as String
 println(jsonString)
} else {
 println("Error in JSON conversion: \(error!.localizedDescription)")
}

Output:

{"keywdict":{"anotherKey":100,"Key2":"Val2"},"bools":[true,false],"a\"b":"c\\d","strings":["string","another"],"numbers":[1,2,3]}
answered Apr 17, 2015 at 19:50
\$\endgroup\$
1
  • \$\begingroup\$ Thanks for the input, @Martin R. For my implementation (which I should have stated) I knew that I only needed to handle [String] arrays and numerics, though I totally goofed on escaping characters! The NSJSONSerialization implementation is CLEARLY the better solution, and I totally missed it. Thanks again. \$\endgroup\$ Commented Apr 17, 2015 at 20:00

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.