Chuyển đổi từ điển sang JSON trong Swift


Câu trả lời:


240

Swift 3.0

Với Swift 3, tên NSJSONSerializationvà phương thức của nó đã thay đổi, theo Nguyên tắc thiết kế API của Swift .

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

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


Tôi nhận được tiếp theo [2: A, 1: A, 3: A]. Nhưng những gì về dấu ngoặc nhọn?
Orkhan Alizade

1
Tôi không hiểu câu hỏi của bạn. Dấu ngoặc nhọn nào? Bạn đã hỏi về việc mã hóa một từ điển trong JSON và đó là câu trả lời của tôi.
Eric Aya

1
Dấu ngoặc nhọn JSON, như{"result":[{"body":"Question 3"}] }
Orkhan Alizade

2
@OrkhanAlizade Cuộc gọi trên dataWithJSONObject sẽ tạo ra "dấu ngoặc nhọn" (tức là dấu ngoặc nhọn) như là một phần của NSDatađối tượng kết quả .
Rob

cảm ơn. lưu ý phụ - xem xét sử dụng d0 thay vì viết tắt (dic) tionary.
johndpope

165

Bạn đang làm một giả định sai. Chỉ vì trình gỡ lỗi / Sân chơi hiển thị từ điển của bạn trong ngoặc vuông (đó là cách Ca cao hiển thị từ điển), điều đó không có nghĩa đó là cách định dạng đầu ra JSON.

Dưới đây là mã ví dụ sẽ chuyển đổi một từ điển chuỗi thành JSON:

Phiên bản 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!)")
}

Để hiển thị ở trên ở định dạng "in đẹp", bạn thay đổi dòng tùy chọn thành:

    options: [.prettyPrinted]

Hoặc trong cú pháp 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!)")

Đầu ra của nó là

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

Hoặc ở định dạng đẹp:

{
  "anotherKey" : "anotherValue",
  "aKey" : "aValue"
}

Từ điển được đặt trong các dấu ngoặc nhọn trong đầu ra JSON, đúng như bạn mong đợi.

BIÊN TẬP:

Trong cú pháp Swift 3/4, đoạn mã trên trông như thế này:

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

Một chuỗi Swift thông thường cũng hoạt động tốt trên khai báoJSONText.
Fred Faust

@thefredelement, Làm thế nào để bạn chuyển đổi NSData trực tiếp thành chuỗi Swift? Chuyển đổi dữ liệu thành chuỗi là một chức năng của NSString.
Duncan C

Tôi đã thực hiện phương pháp này và sử dụng init dữ liệu / mã hóa trên chuỗi Swift, tôi không chắc liệu nó có khả dụng trên Swift 1.x.
Fred Faust

Cứu ngày của tôi. Cảm ơn.
Shobhit C

nên được chọn câu trả lời (y)
iBug

49

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

Lưu ý rằng các khóa và giá trị phải thực hiện Codable. Chuỗi, Ints và Nhân đôi (và hơn thế nữa) đã có Codable. Xem Mã hóa và giải mã các loại tùy chỉnh .


26

Câu trả lời của tôi cho câu hỏi của bạn dưới đây

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)

Câu trả lời là

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

24

DictionaryMở rộng Swift 4 .

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

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

Đây là một cách tốt và có thể tái sử dụng để giải quyết vấn đề nhưng một lời giải thích nhỏ sẽ giúp những người mới đến hiểu rõ hơn về nó.
nilobarp

Điều này có thể được áp dụng nếu các khóa của từ điển có chứa các đối tượng tùy chỉnh không?
Raju yourPepe

2
Nó không phải là ý tưởng tốt để sử dụng encoding: .asciitrong mở rộng công cộng. .utf8Sẽ an toàn hơn nhiều!
ArtFeel

bản in này với các ký tự thoát là có bất cứ nơi nào để ngăn chặn điều đó?
MikeG

23

Đôi khi, cần phải in ra phản hồi của máy chủ cho mục đích gỡ lỗi. Đây là một chức năng tôi sử dụng:

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

}

Ví dụ sử dụng:

(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

Swift 3 :

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

Điều này sẽ sụp đổ nếu bất kỳ phần nào là không, thực hành rất xấu để buộc hủy kết quả. // Dù sao, đã có cùng thông tin (không có sự cố) trong các câu trả lời khác, vui lòng tránh đăng nội dung trùng lặp. Cảm ơn.
Eric Aya

5

Trả lời cho câu hỏi của bạn dưới đây:

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

2

Đây là một phần mở rộng dễ dàng để làm điều này:

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
    }

}

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
Một số sai lầm ở đây. Tại sao sử dụng NSDipedia của Foundation thay vì Từ điển của Swift?! Ngoài ra, tại sao trả về một từ điển mới với giá trị Chuỗi, thay vì trả về dữ liệu JSON thực tế? Điều này không có ý nghĩa. Ngoài ra, tùy chọn không được bao bọc hoàn toàn được trả về như một tùy chọn thực sự không phải là một ý tưởng tốt.
Eric Aya
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.