在Swift中将Dictionary转换为JSON


Answers:


240

斯威夫特3.0

NSJSONSerialization根据Swift API设计指南,对于Swift 3,其名称及其方法已更改。

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

斯威夫特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]。但是花括号呢?
Orkhan Alizade 2015年

1
我不明白你的问题。什么花括号?您问有关用JSON编码字典的问题,这就是我的答案。
Eric Aya 2015年

1
JSON大括号,例如{"result":[{"body":"Question 3"}] }
Orkhan Alizade 2015年

2
@OrkhanAlizade上面的调用dataWithJSONObject 产生“花括号”(即花括号)作为结果NSData对象的一部分。
罗布2015年

谢谢。旁注-考虑使用d0代替(dic)tionary。
johndpope

165

您做出错误的假设。仅仅是因为调试器/游乐场将您的字典显示在方括号中(这就是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声明上也可以正常工作。
Fred Faust

@thefredelement,但是如何将NSData直接转换为Swift字符串?数据到字符串的转换是NSString的功能。
Duncan C

我正在实现此方法,并在Swift字符串上使用了数据/编码init,但不确定在Swift 1.x上是否可用。
Fred Faust

拯救了我的一天。谢谢。
Shobhit C

应该选择答案(y)
iBug

50

斯威夫特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。请参见编码和解码自定义类型


26

我对你问题的回答如下

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: NSUTF8StringEncoding)! as String

print(jsonString)

答案是

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

24

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

这是解决问题的一种很好且可重复使用的方法,但是稍作解释将有助于新手更好地理解它。
nilobarp

如果字典的键包含自定义对象数组,可以应用此方法吗?
Raju yourPepe '19

2
encoding: .ascii在公共扩展中使用它不是一个好主意。.utf8会更安全!
ArtFeel

带有转义字符的打印件是否有防止这种情况的地方?
MikeG

23

有时出于调试目的,有必要打印出服务器的响应。这是我使用的功能:

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

10

迅捷3

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

如果任何部分为零,这将导致崩溃,这是强制解开结果的非常糟糕的做法。//无论如何,其他答案中已经有相同的信息(没有崩溃),请避免发布重复的内容。谢谢。
艾瑞克·艾雅

5

您的问题的答案如下:

斯威夫特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)
        }


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

1
这里有几个错误。为什么要使用Foundation的NSDictionary而不是Swift的Dictionary ?!另外,为什么要返回一个以String作为值的新字典,而不是返回实际的JSON数据?这没有道理。而且,将隐式解开的可选返回为可选确实不是一个好主意。
埃里克·艾雅
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.