Convertir le dictionnaire en JSON dans Swift

188

J'ai créé le prochain dictionnaire:

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

et j'obtiens:

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

Alors, comment puis-je le convertir en JSON?

Orkhan Alizade
la source
1
NSJSONSerialization
Matthias Bauch

Réponses:

240

Swift 3.0

Avec Swift 3, le nom NSJSONSerializationet ses méthodes ont changé, conformément aux directives de conception de l'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)
}

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

Eric Aya
la source
Je reçois le suivant [2: A, 1: A, 3: A]. Mais qu'en est-il des accolades?
Orkhan Alizade
1
Je ne comprends pas votre question. Quelles accolades? Vous avez posé une question sur l'encodage d'un dictionnaire en JSON, et c'est ma réponse.
Eric Aya
1
{"result":[{"body":"Question 3"}] }
Accolades
2
@OrkhanAlizade L'appel ci - dessus pour dataWithJSONObject se produire des « accolades » ( à savoir les accolades) dans le cadre de la résultante NSDataobjet.
Rob
Merci. note latérale - envisagez d'utiliser d0 à la place pour abréger (dic) tionary.
johndpope
166

Vous faites une fausse hypothèse. Ce n'est pas parce que le débogueur / Playground affiche votre dictionnaire entre crochets (c'est ainsi que Cocoa affiche les dictionnaires) que cela ne signifie pas que c'est la façon dont la sortie JSON est formatée.

Voici un exemple de code qui convertira un dictionnaire de chaînes en JSON:

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

Pour afficher ce qui précède dans un format «joli imprimé», vous devez modifier la ligne d'options en:

    options: [.prettyPrinted]

Ou dans la syntaxe 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!)")

Le résultat de cela est

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

Ou dans un joli format:

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

Le dictionnaire est entouré d'accolades dans la sortie JSON, comme vous vous en doutez.

ÉDITER:

Dans la syntaxe Swift 3/4, le code ci-dessus ressemble à ceci:

  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
la source
Une chaîne Swift régulière fonctionne également sur la déclaration JSONText.
Fred Faust
@thefredelement, comment convertir NSData directement en chaîne Swift? La conversion des données en chaîne est une fonction de NSString.
Duncan C
J'implémentais cette méthode et utilisais les données / encodage init sur une chaîne Swift, je ne sais pas si cela était disponible sur Swift 1.x.
Fred Faust
J'ai sauvé ma journée. Merci.
Shobhit C
devrait être sélectionné réponse (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)
    }
}

Notez que les clés et les valeurs doivent être implémentées Codable. Les chaînes, les entiers et les doubles (et plus) le sont déjà Codable. Voir Encodage et décodage de types personnalisés .

Ryan H
la source
26

Ma réponse à votre question est ci-dessous

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)

La réponse est

{
  "0" : "ArrayObjectOne",
  "1" : "ArrayObjecttwo",
  "2" : "ArrayObjectThree"
}
user3182143
la source
24

Parfois, il est nécessaire d'imprimer la réponse du serveur à des fins de débogage. Voici une fonction que j'utilise:

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

}

Exemple d'utilisation:

(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
la source
24

DictionaryExtension 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)
    }
}
thexande
la source
C'est un bon moyen réutilisable de résoudre le problème, mais une petite explication aiderait les nouveaux arrivants à mieux le comprendre.
nilobarp
Cela pourrait-il être appliqué si les clés du dictionnaire contiennent un tableau d'objets personnalisés?
Raju yourPepe
2
Ce n'est pas une bonne idée de l'utiliser encoding: .asciidans l'extension publique. .utf8sera beaucoup plus sûr!
ArtFeel
cela imprime avec des caractères d'échappement y a-t-il un endroit pour empêcher cela?
MikeG le
10

Swift 3 :

let jsonData = try? JSONSerialization.data(withJSONObject: dict, options: [])
let jsonString = String(data: jsonData!, encoding: .utf8)!
print(jsonString)
Bilal
la source
Cela plantera si une partie est nulle, très mauvaise pratique pour forcer le déroulement des résultats. // Quoi qu'il en soit, il y a déjà les mêmes informations (sans le plantage) dans d'autres réponses, veuillez éviter de publier du contenu en double. Merci.
Eric Aya
5

La réponse à votre question est ci-dessous:

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)
        }
Dheeraj D
la source
2

Voici une extension simple pour ce faire:

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
la source
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
la source
1
Plusieurs erreurs ici. Pourquoi utiliser NSDictionary de la Fondation au lieu du dictionnaire de Swift?! Aussi pourquoi renvoyer un nouveau dictionnaire avec une chaîne comme valeur, au lieu de renvoyer les données JSON réelles? Cela n'a pas de sens. De plus, l'option facultative implicitement déroulée renvoyée comme facultative n'est vraiment pas du tout une bonne idée.
Eric Aya