在 Swift 中将字典转换为 JSON

Posted

技术标签:

【中文标题】在 Swift 中将字典转换为 JSON【英文标题】:Convert Dictionary to JSON in Swift 【发布时间】:2015-04-14 10:34:08 【问题描述】:

我已经创建了下一个字典:

var postJSON = [ids[0]:answersArray[0], ids[1]:answersArray[1], ids[2]:answersArray[2]] as Dictionary

我得到:

[2: B, 1: A, 3: C]

那么,如何将其转换为 JSON?

【问题讨论】:

NSJSONSerialization 【参考方案1】:

Swift 3.0

根据Swift API Design Guidelines,在 Swift 3 中,NSJSONSerialization 的名称及其方法已更改。

let dic = ["2": "B", "1": "A", "3": "C"]

do 
    let jsonData = try JSONSerialization.data(withJSONObject: dic, options: .prettyPrinted)
    // here "jsonData" is the dictionary encoded in JSON data

    let decoded = try JSONSerialization.jsonObject(with: jsonData, options: [])
    // here "decoded" is of type `Any`, decoded from JSON data

    // you can now cast it with the right type        
    if let dictFromJSON = decoded as? [String:String] 
        // use dictFromJSON
    
 catch 
    print(error.localizedDescription)


Swift 2.x

do 
    let jsonData = try NSJSONSerialization.dataWithJSONObject(dic, options: NSJSONWritingOptions.PrettyPrinted)
    // here "jsonData" is the dictionary encoded in JSON data

    let decoded = try NSJSONSerialization.JSONObjectWithData(jsonData, options: [])
    // here "decoded" is of type `AnyObject`, decoded from JSON data

    // you can now cast it with the right type 
    if let dictFromJSON = decoded as? [String:String] 
        // use dictFromJSON
    
 catch let error as NSError 
    print(error)


斯威夫特 1

var error: NSError?
if let jsonData = NSJSONSerialization.dataWithJSONObject(dic, options: NSJSONWritingOptions.PrettyPrinted, error: &error) 
    if error != nil 
        println(error)
     else 
        // here "jsonData" is the dictionary encoded in JSON data
    


if let decoded = NSJSONSerialization.JSONObjectWithData(jsonData, options: nil, error: &error) as? [String:String] 
    if error != nil 
        println(error)
     else 
        // here "decoded" is the dictionary decoded from JSON data
    


【讨论】:

我得到了下一个[2: A, 1: A, 3: A]。但是大括号呢? 我不明白你的问题。什么大括号?你问过用 JSON 编码字典,这就是我的回答。 JSON 大括号,如"result":["body":"Question 3"] @OrkhanAlizade 上述对dataWithJSONObject 的调用生成“大括号”(即大括号)作为结果NSData 对象的一部分。 谢谢。旁注 - 考虑使用 d0 代替(字典)字典的缩写。【参考方案2】:

你的假设是错误的。仅仅因为调试器/Playground 在方括号中显示您的字典(这是 Cocoa 显示字典的方式),并不意味着 JSON 输出的格式就是这样。

以下是将字符串字典转换为 JSON 的示例代码:

Swift 3 版本:

import Foundation

let dictionary = ["aKey": "aValue", "anotherKey": "anotherValue"]
if let theJSONData = try? JSONSerialization.data(
    withJSONObject: dictionary,
    options: []) 
    let theJSONText = String(data: theJSONData,
                               encoding: .ascii)
    print("JSON string = \(theJSONText!)")

要以“漂亮打印”格式显示上述内容,您需要将选项行更改为:

    options: [.prettyPrinted]

或者在 Swift 2 语法中:

import Foundation
 
let dictionary = ["aKey": "aValue", "anotherKey": "anotherValue"]
let theJSONData = NSJSONSerialization.dataWithJSONObject(
  dictionary ,
  options: NSJSONWritingOptions(0),
  error: nil)
let theJSONText = NSString(data: theJSONData!,
  encoding: NSASCIIStringEncoding)
println("JSON string = \(theJSONText!)")

输出是

"JSON string = "anotherKey":"anotherValue","aKey":"aValue""

或以漂亮的格式:


  "anotherKey" : "anotherValue",
  "aKey" : "aValue"

正如您所期望的那样,字典在 JSON 输出中用大括号括起来。

编辑:

在 Swift 3/4 语法中,上面的代码如下所示:

  let dictionary = ["aKey": "aValue", "anotherKey": "anotherValue"]
    if let theJSONData = try?  JSONSerialization.data(
      withJSONObject: dictionary,
      options: .prettyPrinted
      ),
      let theJSONText = String(data: theJSONData,
                               encoding: String.Encoding.ascii) 
          print("JSON string = \n\(theJSONText)")
    
  

【讨论】:

一个普通的 Swift 字符串同样适用于 JSONText 声明。 @thefredelement,您如何将 NSData 直接转换为 Swift 字符串?数据到字符串的转换是 NSString 的一个函数。 我正在实现这个方法并在 Swift 字符串上使用了数据/编码初始化,我不确定它是否在 Swift 1.x 上可用。 拯救了我的一天。谢谢。 应该选择答案(y)【参考方案3】:

斯威夫特 5:

let dic = ["2": "B", "1": "A", "3": "C"]
let encoder = JSONEncoder()
if let jsonData = try? encoder.encode(dic) 
    if let jsonString = String(data: jsonData, encoding: .utf8) 
        print(jsonString)
    

请注意,键和值必须实现 Codable。字符串、整数和双精度(以及更多)已经是 Codable。见Encoding and Decoding Custom Types。

另请注意:如评论中所述,Any 不符合Codable。将您的数据调整为 Codable 可能仍然是一种好方法,以便您使用 Swift 类型(尤其是在您还要解码任何编码的 json 的情况下),这样您就可以更具声明性关于编码的结果。

【讨论】:

仅供参考,如果您的 dict 是 [String, Any] 类型,此解决方案将不起作用【参考方案4】:

我对你的问题的回答如下

let dict = ["0": "ArrayObjectOne", "1": "ArrayObjecttwo", "2": "ArrayObjectThree"]

var error : NSError?

let jsonData = try! NSJSONSerialization.dataWithJSONObject(dict, options: NSJSONWritingOptions.PrettyPrinted)

let jsonString = NSString(data: jsonData, encoding: String.Encoding.utf8.rawValue)! as String

print(jsonString)

答案是


  "0" : "ArrayObjectOne",
  "1" : "ArrayObjecttwo",
  "2" : "ArrayObjectThree"

【讨论】:

【参考方案5】:

Swift 4 Dictionary 扩展。

extension Dictionary 
    var jsonStringRepresentation: String? 
        guard let theJSONData = try? JSONSerialization.data(withJSONObject: self,
                                                            options: [.prettyPrinted]) else 
            return nil
        

        return String(data: theJSONData, encoding: .ascii)
    

【讨论】:

这是解决问题的好方法和可重复使用的方法,但稍微解释一下会帮助新手更好地理解它。 如果字典的键包含自定义对象数组,这可以应用吗? 在公共扩展中使用encoding: .ascii 不是一个好主意。 .utf8 会更安全! 这个带有转义字符的打印有什么地方可以防止这种情况发生吗?【参考方案6】:

有时需要打印出服务器的响应以进行调试。这是我使用的一个函数:

extension Dictionary 

    var json: String 
        let invalidJson = "Not a valid JSON"
        do 
            let jsonData = try JSONSerialization.data(withJSONObject: self, options: .prettyPrinted)
            return String(bytes: jsonData, encoding: String.Encoding.utf8) ?? invalidJson
         catch 
            return invalidJson
        
    

    func printJson() 
        print(json)
    


使用示例:

(lldb) po dictionary.printJson()

  "InviteId" : 2,
  "EventId" : 13591,
  "Messages" : [
    
      "SenderUserId" : 9514,
      "MessageText" : "test",
      "RecipientUserId" : 9470
    ,
    
      "SenderUserId" : 9514,
      "MessageText" : "test",
      "RecipientUserId" : 9470
    
  ],
  "TargetUserId" : 9470,
  "InvitedUsers" : [
    9470
  ],
  "InvitingUserId" : 9514,
  "WillGo" : true,
  "DateCreated" : "2016-08-24 14:01:08 +00:00"

【讨论】:

【参考方案7】:

斯威夫特 5:

extension Dictionary 
    
    /// Convert Dictionary to JSON string
    /// - Throws: exception if dictionary cannot be converted to JSON data or when data cannot be converted to UTF8 string
    /// - Returns: JSON string
    func toJson() throws -> String 
        let data = try JSONSerialization.data(withJSONObject: self)
        if let string = String(data: data, encoding: .utf8) 
            return string
        
        throw NSError(domain: "Dictionary", code: 1, userInfo: ["message": "Data cannot be converted to .utf8 string"])
    

【讨论】:

这适用于 Codable 类型,但要小心 String: Any,这会产生不正确的值!【参考方案8】:

Swift 3

let jsonData = try? JSONSerialization.data(withJSONObject: dict, options: [])
let jsonString = String(data: jsonData!, encoding: .utf8)!
print(jsonString)

【讨论】:

如果任何部分为零,这将崩溃,强制展开结果是非常糟糕的做法。 // 无论如何,其他答案中已经有相同的信息(没有崩溃),请避免发布重复的内容。谢谢。【参考方案9】:

您的问题的答案如下:

斯威夫特 2.1

     do 
          if let postData : NSData = try NSJSONSerialization.dataWithJSONObject(dictDataToBeConverted, options: NSJSONWritingOptions.PrettyPrinted)

          let json = NSString(data: postData, encoding: NSUTF8StringEncoding)! as String
          print(json)

        
        catch 
           print(error)
        

【讨论】:

【参考方案10】:

在 Swift 5.4 中

extension Dictionary 
    var jsonData: Data? 
        return try? JSONSerialization.data(withJSONObject: self, options: [.prettyPrinted])
    
    
    func toJSONString() -> String? 
        if let jsonData = jsonData 
            let jsonString = String(data: jsonData, encoding: .utf8)
            return jsonString
        
        
        return nil
    

将它作为变量的想法是因为你可以像这样重用它:

extension Dictionary 
    func decode<T:Codable>() throws -> T 
        return try JSONDecoder().decode(T.self, from: jsonData ?? Data())
    

【讨论】:

这适用于 Codable 类型,但要小心 String: Any,这会产生不正确的值! @Wo_0NDeR 哪个属性或方法会产生不正确的值?【参考方案11】:

这是一个简单的扩展:

https://gist.github.com/stevenojo/0cb8afcba721838b8dcb115b846727c3

extension Dictionary 
    func jsonString() -> NSString? 
        let jsonData = try? JSONSerialization.data(withJSONObject: self, options: [])
        guard jsonData != nil else return nil
        let jsonString = String(data: jsonData!, encoding: .utf8)
        guard jsonString != nil else return nil
        return jsonString! as NSString
    


【讨论】:

【参考方案12】:

使用lldb

(lldb) p JSONSerialization.data(withJSONObject: notification.request.content.userInfo, options: [])
(Data) $R16 = 375 bytes
(lldb) p String(data: $R16!, encoding: .utf8)!
(String) $R18 = "\"aps\": \"some_text\""

//or
p String(data: JSONSerialization.data(withJSONObject: notification.request.content.userInfo, options: [])!, encoding: .utf8)!
(String) $R4 = "\"aps\": \"some_text\""

【讨论】:

【参考方案13】:

这对我有用:

import SwiftyJSON

extension JSON 
    
    mutating func appendIfKeyValuePair(key: String, value: Any)
        if var dict = self.dictionaryObject 
            dict[key] = value
            self = JSON(dict)
        
    

用法:

var data: JSON = []

data.appendIfKeyValuePair(key: "myKey", value: "myValue")

【讨论】:

【参考方案14】:
private func convertDictToJson(dict : NSDictionary) -> NSDictionary?

    var jsonDict : NSDictionary!

    do 
        let jsonData = try JSONSerialization.data(withJSONObject:dict, options:[])
        let jsonDataString = String(data: jsonData, encoding: String.Encoding.utf8)!
        print("Post Request Params : \(jsonDataString)")
        jsonDict = [ParameterKey : jsonDataString]
        return jsonDict
     catch 
        print("JSON serialization failed:  \(error)")
        jsonDict = nil
    
    return jsonDict

【讨论】:

这里有几个错误。为什么使用 Foundation 的 NSDictionary 而不是 Swift 的 Dictionary?!另外,为什么要返回一个以字符串为值的新字典,而不是返回实际的 JSON 数据?这没有意义。此外,作为可选项返回的隐式展开的可选项也不是一个好主意。

以上是关于在 Swift 中将字典转换为 JSON的主要内容,如果未能解决你的问题,请参考以下文章

在 Swift 3 中将 JSON 字符串转换为字典

在 SWIFT 中将 JSON 解析为字典对象

在 Swift/Xcode 中将 JSON 文件转换为数组

在ios中将json转换为字典

如何将afnetworking json字典转换为字符串,然后在IOS中将字符串转换为字典?

在python中将JSON字典转换为JSON数组