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) + "}"
}
-
1\$\begingroup\$ Welcome to CodeReview, Andrew. I hope you get some fine answers. \$\endgroup\$Legato– Legato2015年04月17日 16:27:05 +00:00Commented Apr 17, 2015 at 16:27
1 Answer 1
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]}
-
\$\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\$Andrew Robinson– Andrew Robinson2015年04月17日 20:00:58 +00:00Commented Apr 17, 2015 at 20:00