如何将字典数组转换为JSON?

11

我有一个字典数组,想将其转换为JSON格式。我的对象类型为[[String: AnyObject]],希望最终得到类似于以下示例的结果:

[
  { "abc": 123, "def": "ggg", "xyz": true },
  { "abc": 456, "def": "hhh", "xyz": false },
  { "abc": 789, "def": "jjj", "xyz": true }
]

这就是我尝试的,但编译器不喜欢我的声明:

extension Array where Element == Dictionary<String, AnyObject> {
    var json: String {
        do { return try? NSJSONSerialization.dataWithJSONObject(self, options: []) ?? "[]" }
        catch { return "[]" }
    }
}

我该如何做到这一点?


所以你的问题不是关于JSON生成,而是约束元素。 - vikingosegundo
dataWithJSONObject 在成功时返回 NSData,因此至少需要创建一个字符串来返回。 - vadian
4个回答

14
通过扩展CollectionType就可以简单地实现这一点。
使用可选绑定和向下转型,将其序列化为数据,然后转换为字符串。
extension CollectionType where Generator.Element == [String:AnyObject] {
    func toJSONString(options: NSJSONWritingOptions = .PrettyPrinted) -> String {
        if let arr = self as? [[String:AnyObject]],
            let dat = try? NSJSONSerialization.dataWithJSONObject(arr, options: options),
            let str = String(data: dat, encoding: NSUTF8StringEncoding) {
            return str
        }
        return "[]"
    }
}

let arrayOfDictionaries: [[String:AnyObject]] = [
    ["abc":123, "def": "ggg", "xyz": true],
    ["abc":456, "def": "hhh", "xyz": false]
]

print(arrayOfDictionaries.toJSONString())

输出:

[
  {
    "abc" : 123,
    "def" : "ggg",
    "xyz" : true
  },
  {
    "abc" : 456,
    "def" : "hhh",
    "xyz" : false
  }
]

这将解决提问者的问题,但会引入一些微妙的错误,例如字典被转换为 [] 而不是它们的 JSON 等效物。我认为提问者也希望获得类型安全,这将防止像这样的运行时问题。 - Cristik
@Cristik 不错的想法。我已经给这个扩展添加了类型约束。现在它应该更接近OP所想要的了。 - Eric Aya
当我创建arrayOfDictionaries时,我遇到了“表达式类型不明确”的错误。这可能需要另一个问题来解决,但它使得这个解决方案无法工作... - teradyl

10

Swift 4:

extension Collection where Iterator.Element == [String:AnyObject] {
    func toJSONString(options: JSONSerialization.WritingOptions = .prettyPrinted) -> String {
        if let arr = self as? [[String:AnyObject]],
            let dat = try? JSONSerialization.data(withJSONObject: arr, options: options),
            let str = String(data: dat, encoding: String.Encoding.utf8) {
            return str
        }
        return "[]"
    }
}

用法:

let arrayOfDictionaries = [
  { "abc": 123, "def": "ggg", "xyz": true },
  { "abc": 456, "def": "hhh", "xyz": false },
  { "abc": 789, "def": "jjj", "xyz": true }
]

print(arrayOfDictionaries.toJSONString())

1
返回错误(key: String,value: Any)无法转换为[字符串:任何]。 - J.Arji

2

Swift 5中,我需要将AnyObject更改为Any,这是在Eric和A.G.的解决方案基础上构建的。

extension Collection where Iterator.Element == [String: Any] {
  func toJSONString(options: JSONSerialization.WritingOptions = .prettyPrinted) -> String {
    if let arr = self as? [[String: Any]],
       let dat = try? JSONSerialization.data(withJSONObject: arr, options: options),
       let str = String(data: dat, encoding: String.Encoding.utf8) {
      return str
    }
    return "[]"
  }
}

使用方法:

let arrayOfDictionaries = [
  { "abc": 123, "def": "ggg", "xyz": true },
  { "abc": 456, "def": "hhh", "xyz": false },
  { "abc": 789, "def": "jjj", "xyz": true }
]

print(arrayOfDictionaries.toJSONString())

0

我认为你试图扩展Array是没有成功的机会的,因为在扩展实体时不可能有相同类型的要求。

你可以使用自由函数:

func jsonify(array: [[String:AnyObject]]) { 
...
}

这样做可以保持您想要的类型安全,但需要移动函数位置。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接