Перетворити словник в JSON в Swift


Відповіді:


240

Swift 3.0

З Swift 3 ім'я NSJSONSerializationта його методи змінилися відповідно до Правил дизайну 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)
}

Швидкий 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]. А як щодо фігурних дужок?
Орхан Алізаде

1
Я не розумію вашого запитання. Які фігурні дужки? Ви запитали про кодування словника в JSON, і це моя відповідь.
Ерік Айя

1
Фігурні дужки JSON, як-от{"result":[{"body":"Question 3"}] }
Орхан Алізаде

2
@OrkhanAlizade наведеного вище виклику dataWithJSONObject буде виробляти «фігурні дужки» (тобто дужки) як частина отриманого NSDataоб'єкта.
Роб

Дякую. бічна примітка - розглянути можливість використання d0 замість скорочення (dic) tionary.
johndpope

166

Ви робите неправильне припущення. Тільки тому, що налагоджувач / майданчик показує ваш словник у квадратних дужках (саме так какао відображає словники), це не означає, що таким чином форматується вихід 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.
Duncan C

Я реалізовував цей метод і використовував дані / кодування init на рядку Swift, я не впевнений, чи було це доступно в Swift 1.x.
Фред Фауст

Врятував мій день. Дякую.
Shobhit C

повинна бути обрана відповідь (у)
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

DictionaryРозширення 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)
    }
}

Це хороший і багаторазовий спосіб вирішення проблеми, але невелике пояснення допоможе новим бажаючим зрозуміти її краще.
nilobarp

Чи можна це застосувати, якщо ключі словника містять масив спеціальних об'єктів?
Raju yourPepe

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

2

Ось просте розширення для цього:

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
Тут кілька помилок. Навіщо використовувати NSDictionary Foundation замість словника Swift ?! Також навіщо повертати новий словник зі значенням String замість повернення фактичних даних JSON? Це не має сенсу. Також неявно розгорнута необов'язкова повертається як необов'язкова насправді зовсім не гарна ідея.
Ерік Айя
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.