Преобразовать словарь в JSON в Swift


Ответы:


240

Swift 3.0

В Swift 3 имя NSJSONSerializationи его методы изменились в соответствии с Руководством по разработке Swift API .

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]. Но как насчет фигурных скобок?
Орхан Ализаде

1
Я не понимаю твой вопрос. Какие фигурные скобки? Вы спрашивали о кодировании словаря в JSON, и это мой ответ.
Эрик Ая

1
JSON фигурные скобки, как{"result":[{"body":"Question 3"}] }
Орхан Ализаде

2
@OrkhanAlizade Приведенный выше вызов dataWithJSONObject приведет к получению «фигурных скобок» (т.е. фигурных скобок) как части получающегося NSDataобъекта.
Роб

Спасибо. примечание стороны - рассмотрите возможность использования d0 вместо сокращения (словарного).
johndpope

166

Вы делаете неправильное предположение. То, что отладчик / игровая площадка отображает ваш словарь в квадратных скобках (то есть, как 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.
Дункан C

Я реализовывал этот метод и использовал инициализацию данных / кодирования в строке Swift, я не уверен, что она была доступна в Swift 1.x.
Фред Фауст

Спас мой день. Спасибо.
Шобхит С

должен быть выбран ответ (у)
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. Strings, Ints и Doubles (и более) уже есть 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

Иногда необходимо распечатать ответ сервера для целей отладки. Вот функция, которую я использую:

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

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

эта печать с escape-символами есть где-нибудь, чтобы предотвратить это?
MikeG

10

Свифт 3 :

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

Это приведет к сбою, если какая-либо часть будет нулевой, очень плохая практика, чтобы принудительно развернуть результаты. // В любом случае такая же информация (без сбоя) уже есть в других ответах, пожалуйста, избегайте публикации дублированного контента. Спасибо.
Эрик Ая

5

Ответ на ваш вопрос ниже:

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

Вот простое расширение, чтобы сделать это:

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 Фонда вместо словаря Swift? Кроме того, зачем возвращать новый словарь с String в качестве значения, а не возвращать фактические данные JSON? Это не имеет смысла. Также неявно развернутый необязательный параметр, возвращаемый как необязательный, на самом деле не очень хорошая идея.
Эрик Ая
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.