【问题标题】:How to convert array of dictionary to JSON?如何将字典数组转换为 JSON?
【发布时间】:2017-01-19 05:39:44
【问题描述】:

我有一个字典数组,我想将它们转换为 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 生成,而是关于约束元素。
  • dataWithJSONObject 成功返回NSData,所以至少你必须创建一个字符串才能返回。

标签: json swift dictionary swift2


【解决方案1】:

实现这一点的一个简单方法是扩展 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 好主意。我为扩展添加了类型约束。它应该更接近 OP 想要的。
  • 我在创建 arrayOfDictionaries 时遇到了 Type of expression is ambiguous without more context 错误。这可能需要一个不同的问题,但它使这个解决方案不起作用......
【解决方案2】:

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())

【讨论】:

  • 返回错误(键:字符串,值:任意)'不可转换为'[字符串:任意]'
【解决方案3】:

Swift 5,我不得不将其更改为 Any 而不是 AnyObject,以 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())

【讨论】:

    【解决方案4】:

    我认为您尝试扩展 Array 很不走运,因为扩展实体时不可能满足相同类型的要求。

    你可以做的是利用免费功能:

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

    这样您将保持所需的类型安全,但需要移动函数位置。

    【讨论】:

      猜你喜欢
      • 2018-05-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-28
      相关资源
      最近更新 更多