【问题标题】:Convert Dictionary to JSON in Swift在 Swift 中将字典转换为 JSON
【发布时间】:2015-06-19 22:23:06
【问题描述】:

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

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

我得到:

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

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

【问题讨论】:

标签: json swift serialization


【解决方案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】:

      斯威夫特 3

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

      【讨论】:

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

      斯威夫特 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,这会产生不正确的值!
      【解决方案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 数据?这没有意义。此外,作为可选项返回的隐式展开的可选项也不是一个好主意。
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2018-03-30
              • 2015-08-25
              • 2017-03-05
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多