Convertir le dictionnaire en JSON dans Swift


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


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

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 .


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

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

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

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)

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

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
    }

}

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
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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.