Konversi Kamus ke JSON di Swift

188

Saya telah membuat Kamus berikutnya:

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

dan saya mendapatkan:

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

Jadi, bagaimana saya bisa mengubahnya menjadi JSON?

Orkhan Alizade
sumber
1
NSJSONSerialization
Matthias Bauch

Jawaban:

240

Swift 3.0

Dengan Swift 3, nama NSJSONSerializationdan metodenya telah berubah, sesuai dengan Pedoman Desain API 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)
}

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

Eric Aya
sumber
Saya mendapatkan yang berikutnya [2: A, 1: A, 3: A]. Tapi bagaimana dengan kurung keriting?
Orkhan Alizade
1
Saya tidak mengerti pertanyaan Anda. Kurung keriting apa? Anda bertanya tentang penyandian kamus di JSON, dan itulah jawaban saya.
Eric Aya
1
Kurung keriting JSON, seperti{"result":[{"body":"Question 3"}] }
Orkhan Alizade
2
@OrkhanAlizade Panggilan ke atas dataWithJSONObject akan menghasilkan "kurung keriting" (yaitu kurung kurawal) sebagai bagian dari NSDataobjek yang dihasilkan .
Rob
Terima kasih. catatan tambahan - pertimbangkan untuk menggunakan d0 sebagai ganti singkatan (dic).
johndpope
166

Anda membuat asumsi yang salah. Hanya karena debugger / Playground menunjukkan kamus Anda dalam tanda kurung siku (yang merupakan cara Cocoa menampilkan kamus) itu tidak berarti itu adalah cara output JSON diformat.

Berikut adalah contoh kode yang akan mengonversi kamus string ke JSON:

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

Untuk menampilkan di atas dalam format "cukup dicetak" Anda akan mengubah baris opsi ke:

    options: [.prettyPrinted]

Atau dalam sintaks 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!)")

Output dari itu adalah

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

Atau dalam format cantik:

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

Kamus terlampir dalam kurung kurawal di output JSON, seperti yang Anda harapkan.

EDIT:

Dalam sintaks Swift 3/4, kode di atas terlihat seperti ini:

  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)")
    }
  }
Duncan C
sumber
String Swift biasa juga berfungsi pada deklarasi JSONText.
Fred Faust
@thefredelement, Bagaimana Anda mengubah NSData langsung ke string Swift? Konversi data ke string adalah fungsi dari NSString.
Duncan C
Saya menerapkan metode ini dan menggunakan init data / encoding pada string Swift, saya tidak yakin apakah itu tersedia di Swift 1.x.
Fred Faust
Menyelamatkan hariku. Terima kasih.
Shobhit C
harus dipilih jawaban (y)
iBug
50

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

Perhatikan bahwa kunci dan nilai harus diimplementasikan Codable. String, Ints, dan Doubles (dan banyak lagi) sudah Codable. Lihat Encoding dan Decoding Jenis Kustom .

Ryan H
sumber
26

Jawaban saya untuk pertanyaan Anda ada di bawah ini

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)

Jawabannya adalah

{
  "0" : "ArrayObjectOne",
  "1" : "ArrayObjecttwo",
  "2" : "ArrayObjectThree"
}
pengguna3182143
sumber
24

DictionaryPerpanjangan cepat 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)
    }
}
thexande
sumber
Ini adalah cara yang baik dan dapat digunakan kembali untuk menyelesaikan masalah tetapi sedikit penjelasan akan membantu pendatang baru untuk memahaminya dengan lebih baik.
nilobarp
Mungkinkah ini diterapkan jika kunci kamus berisi larik objek khusus?
Raju yourPepe
2
Ini bukan ide yang baik untuk digunakan encoding: .asciidalam ekstensi publik. .utf8akan jauh lebih aman!
ArtFeel
ini mencetak dengan karakter pelarian adakah yang bisa mencegahnya?
MikeG
23

Terkadang perlu untuk mencetak respons server untuk tujuan debugging. Inilah fungsi yang saya gunakan:

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

}

Contoh penggunaan:

(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"
}
Andrey Gordeev
sumber
10

Swift 3 :

let jsonData = try? JSONSerialization.data(withJSONObject: dict, options: [])
let jsonString = String(data: jsonData!, encoding: .utf8)!
print(jsonString)
Bilal
sumber
Ini akan macet jika ada bagian yang nihil, praktik yang sangat buruk untuk memaksa membuka hasil. // Pokoknya sudah ada informasi yang sama (tanpa crash) di jawaban lain, harap hindari memposting konten duplikat. Terima kasih.
Eric Aya
5

Jawaban untuk pertanyaan Anda adalah di bawah ini:

Cepat 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)
        }
Dheeraj D
sumber
2

Berikut ini adalah ekstensi mudah untuk melakukan ini:

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
    }

}
StevenOjo
sumber
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
}
Swati Desai
sumber
1
Beberapa kesalahan di sini. Mengapa menggunakan Foundation's NSDictionary daripada Swift's Dictionary ?! Juga mengapa mengembalikan kamus baru dengan String sebagai nilai, alih-alih mengembalikan data JSON yang sebenarnya? Ini tidak masuk akal. Selain itu, opsi yang secara implisit tidak dibuka yang dikembalikan sebagai opsional sebenarnya bukan ide yang baik sama sekali.
Eric Aya