web-dev-qa-db-fra.com

Est-il possible d'imprimer joliment Swift dictionnaires sur la console?

NSDictionary *dictionary = @{@"A" : @"alfa",
                             @"B" : @"bravo",
                             @"C" : @"charlie",
                             @"D" : @"delta",
                             @"E" : @"echo",
                             @"F" : @"foxtrot"};
NSLog(@"%@", dictionary.description);

imprime ce qui suit sur la console:

{
    A = alfa;
    B = bravo;
    C = charlie;
    D = delta;
    E = echo;
    F = foxtrot;
}

let dictionary: [String : String] = ["A" : "alfa",
                                     "B" : "bravo",
                                     "C" : "charlie",
                                     "D" : "delta",
                                     "E" : "echo",
                                     "F" : "foxtrot"];
print(dictionary)

imprime ce qui suit sur la console:

["B": "bravo", "A": "alfa", "F": "foxtrot", "C": "charlie", "D": "delta", "E": "echo"]

Existe-t-il un moyen dans Swift d'obtenir dans de jolis dictionnaires d'impression dans lesquels chaque paire clé-valeur occupe une nouvelle ligne?

68
Toland Hon

Vous pouvez utiliser dump , par exemple, si l'objectif est d'inspecter le dictionnaire. dump fait partie de la bibliothèque standard de Swift.

Usage:

let dictionary: [String : String] = ["A" : "alfa",
                                     "B" : "bravo",
                                     "C" : "charlie",
                                     "D" : "delta",
                                     "E" : "echo",
                                     "F" : "foxtrot"]

dump(dictionary)

Sortie:

enter image description here


dump imprime le contenu d'un objet par réflexion (miroir).

Vue détaillée d'un tableau:

let names = ["Joe", "Jane", "Jim", "Joyce"]
dump(names)

Impressions:

4 éléments
- [0]: Joe
- [1]: Jane
- [2]: Jim
- [3]: Joyce

Pour un dictionnaire:

let attributes = ["foo": 10, "bar": 33, "baz": 42]
dump(attributes)

Impressions:

▿ 3 paires clé/valeur
▿ [0]: (2 éléments)
- .0: bar
- .1: 33
▿ [1]: (2 éléments)
- .0: baz
- .1: 42
▿ [2]: (2 éléments)
- .0: foo
- .1: 10

dump est déclaré comme dump(_:name:indent:maxDepth:maxItems:).

Le premier paramètre n'a pas d'étiquette.

Il y a d'autres paramètres disponibles, comme name pour définir une étiquette pour l'objet inspecté:

dump(attributes, name: "mirroring")

Impressions:

▿ mise en miroir: 3 paires clé/valeur
▿ [0]: (2 éléments)
- .0: bar
- .1: 33
▿ [1]: (2 éléments)
- .0: baz
- .1: 42
▿ [2]: (2 éléments)
- .0: foo
- .1: 10

Vous pouvez également choisir d'imprimer seulement un certain nombre d'éléments avec maxItems:, d'analyser l'objet jusqu'à une certaine profondeur avec maxDepth: et de modifier l'indentation des objets imprimés avec indent:.

75
ayaio

Lancer un dictionnaire sur 'AnyObject' était pour moi la solution la plus simple:

let dictionary = ["a":"b",
                  "c":"d",
                  "e":"f"]
print("This is the console output: \(dictionary as AnyObject)")

this is the console output

C’est plus facile à lire pour moi que l’option dump, mais notez que cela ne vous donnera pas le nombre total de valeurs-clés.

72
Jalakoo

solution de solution

Pour ceux d'entre vous qui veulent voir Dictionary en JSON sans séquence d'échappement dans console, voici un moyen simple de le faire.

(lldb) p print(String(data: try! JSONSerialization.data(withJSONObject: object, options: .prettyPrinted), encoding: .utf8 )!)

65
Irshad Mohamed

Juste une autre façon en utilisant la programmation fonctionnelle

dictionary.forEach { print("\($0): \($1)") }

Sortie

B: bravo
A: alfa
F: foxtrot
C: charlie
D: delta
E: echo
31
Luca Angeletti

À des fins de débogage uniquement, je convertis le tableau ou le dictionnaire en un json joliment imprimé:

public extension Collection {

    /// Convert self to JSON String.
    /// - Returns: Returns the JSON as String or empty string if error while parsing.
    func json() -> String {
        do {
            let jsonData = try JSONSerialization.data(withJSONObject: self, options: [.prettyPrinted])
            guard let jsonString = String(data: jsonData, encoding: String.Encoding.utf8) else {
                print("Can't create string with data.")
                return "{}"
            }
            return jsonString
        } catch let parseError {
            print("json serialization error: \(parseError)")
            return "{}"
        }
    }
}

Ensuite:

print("\nHTTP request: \(URL)\nParams: \(params.json())\n")

Résultat sur console:

HTTP request: https://example.com/get-data
Params: {
  "lon" : 10.8663676,
  "radius" : 111131.8046875,
  "lat" : 23.8063882,
  "index_start" : 0,
  "uid" : 1
}
19
Marco M

Je ne considérerais pas que beaucoup des réponses fournies ici sont de véritables JSON joliment imprimés, car lorsque vous transmettez les résultats à un validateur JSON, le résultat est invalide (souvent à cause du code incluant '=' plutôt que ':').

La méthode la plus simple que j'ai trouvée consiste simplement à convertir l'objet JSON en données à l'aide de la jolie option d'écriture imprimée, puis à imprimer une chaîne à l'aide des données obtenues.

Voici un exemple:

let jsonData = try! JSONSerialization.data(withJSONObject: parameters, options: .prettyPrinted)

if let jsonString = String(data: jsonData, encoding: .utf8) {
    print(jsonString)
}

Résultat:

{
    "jsonData": [
        "Some String"
    ],
    "moreJSONData": "Another String",
    "evenMoreJSONData": {
        "A final String": "awd"
    }
}

EDIT: Il a été signalé que l’opérateur n’avait pas demandé le format JSON, mais j’estime que les réponses recommandant simplement d’imprimer ou de transférer les données dans la console fournissent très peu de formatage (le cas échéant) et ne sont donc pas jolis d'impression.

Je crois que, malgré le fait que l’OP ne demande pas de JSON, c’est une réponse viable, car il s’agit d’un format de données beaucoup plus lisible que le format horrible qui a été craché dans la console par xcode/Swift.

9
James Wolfe

Vous pouvez simplement utiliser une boucle for et imprimer chaque itération

for (key,value) in dictionary { 
    print("\(key) = \(value)")
}

Application en extension:

extension Dictionary where Key: CustomDebugStringConvertible, Value:CustomDebugStringConvertible {

    var prettyprint : String {
        for (key,value) in self {
            print("\(key) = \(value)")
        }

        return self.description
    }
}

Autre application:

extension Dictionary where Key: CustomDebugStringConvertible, Value:CustomDebugStringConvertible {

    func prettyPrint(){
        for (key,value) in self {
            print("\(key) = \(value)")
        }
    }
}

Usage:

dictionary.prettyprint //var prettyprint
dictionary.prettyPrint //func prettyPrint

Sortie (Testé dans Xcode 8 beta 2 Playground):

A = alfa
B = bravo
C = charlie
D = delta
E = echo
F = foxtrot
5
Asdrubal

Pour Swift (& s'appuyant sur la réponse brillante de @ Jalakoo), créez l'extension Dictionary suivante:

extension Dictionary where Key: ExpressibleByStringLiteral, Value: Any {
    var prettyPrint: String {
        return String(describing: self as AnyObject)
    }
}

puis imprimez un dictionnaire de toute hiérarchie de façon jolie (mieux que dump()) en utilisant ceci:

print(dictionary!.prettyPrint)
4
AbdelHady

La méthodologie de conversion du Swift Dictionary en json et en aller-retour est la plus simple. J'utilise généralement le cisea de Facebook qui a une commande pjson pour imprimer un dictionnaire Swift. Par exemple:

(lldb) pjson dict as NSDictionary

Cela devrait joliment imprimer le dictionnaire. C'est une façon beaucoup plus propre de faire ce qui a déjà été suggéré. P.S. Pour le moment, vous devrez transtypter dict en tant que NSDictionary car le moteur d’exécution d’Objective-C ne comprend pas les dictionnaires Swift. J'ai déjà soulevé un PR sur le ciseau pour me débarrasser de cette restriction.

2
jarora

Détails

  • Xcode 10.2.1 (10E1001), Swift 5

Solution

extension Dictionary {
    func format(options: JSONSerialization.WritingOptions) -> Any? {
        do {
            let jsonData = try JSONSerialization.data(withJSONObject: self, options: options)
            return try JSONSerialization.jsonObject(with: jsonData, options: [.allowFragments])
        } catch {
            print(error.localizedDescription)
            return nil
        }
    }
}

Usage

let dictionary: [String : Any] = [
                                    "id": 0,
                                    "bool": true,
                                    "int_array": [1,3,5],
                                    "dict_array": [
                                        ["id": 1, "text": "text1"],
                                        ["id": 1, "text": "text2"]
                                    ]
                                 ]
print("Regualr print:\n\(dictionary)\n")
guard let formatedDictionary = dictionary.format(options: [.prettyPrinted, .sortedKeys]) else { return }
print("Pretty printed:\n\(formatedDictionary)\n")

Résultats

enter image description here

1
Vasily Bodnarchuk

Que diriez-vous:

import Foundation

extension Dictionary {
    var myDesc: String {
        get {
            var v = ""
            for (key, value) in self {
                v += ("\(key) = \(value)\n")
            }
            return v
        }
    }
}


// Then, later, for any dictionary:
print(dictionary.myDesc)
0
BaseZen
extension String {

    var conslePrintString: String {

        guard let data = "\""
            .appending(
                replacingOccurrences(of: "\\u", with: "\\U")
                    .replacingOccurrences(of: "\"", with: "\\\"")
            )
            .appending("\"")
            .data(using: .utf8) else {

            return self
        }

        guard let propertyList = try? PropertyListSerialization.propertyList(from: data,
                                                                             options: [],
                                                                             format: nil) else {
            return self
        }

        guard let string = propertyList as? String else {
            return self
        }

        return string.replacingOccurrences(of: "\\r\\n", with: "\n")
    }
}

let code in extension String and it works fine 

let string = "\(jsonDictionary)".conslePrintString
0
hasayakey