HiveBrain v1.2.0
Get Started
← Back to all entries
patternswiftMinor

Swift extension: Dictionary<String, AnyObject> to JSON string for URL parameter

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
swifturlextensionparameterforjsondictionarystringanyobject

Problem

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 {
      valStr = val.toJSONString() // recursion for nested dictionaries
    } else if let val = val as? Array {
      let tmpStr = "\",\"".join(val)
      valStr = "[\"\(tmpStr)\"]"
    } else if let val = val as? NSNumber {
      valStr = "\(val)"
    }
    pcs.append("\"\(key)\":\(valStr)")
  }
  return "{" + ",".join(pcs) + "}"
}

Solution

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]}

Code Snippets

[ "a\"b" : "c\\d"].toJSONString()
[ "key" : true].toJSONString()
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)")
}

Context

StackExchange Code Review Q#87210, answer score: 5

Revisions (0)

No revisions yet.