it-roy-ru.com

Есть ли способ вывести на консоль Swift словари?

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

выводит на консоль следующее:

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

выводит на консоль следующее:

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

Есть ли способ в Swift получить его в симпатичных печатных словарях, где каждая пара ключ-значение занимает новую строку?

64
Toland Hon

Например, вы можете использовать dump , если целью является проверка словаря. dump является частью стандартной библиотеки Swift.

Использование:

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

dump(dictionary)

Результат:

enter image description here


dump печатает содержимое объекта через отражение (зеркальное отображение).

Детальный просмотр массива:

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

Печать:

Elements 4 элемента
- [0]: Джо
- [1]: Джейн
- [2]: Джим
- [3]: Джойс

Для словаря:

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

Печать:

Pairs 3 пары ключ/значение
▿ [0]: (2 элемента)
- .0: бар
- .1: 33
▿ [1]: (2 элемента)
- .0: баз
- .1: 42
▿ [2]: (2 элемента)
- .0: foo
- .1: 10

dump объявляется как dump(_:name:indent:maxDepth:maxItems:).

Первый параметр не имеет метки.

Доступны другие параметры, такие как name, чтобы установить метку для проверяемого объекта:

dump(attributes, name: "mirroring")

Печать:

▿ зеркалирование: 3 пары ключ/значение
▿ [0]: (2 элемента)
- .0: бар
- .1: 33
▿ [1]: (2 элемента)
- .0: баз
- .1: 42
▿ [2]: (2 элемента)
- .0: foo
- .1: 10

Вы также можете распечатать только определенное количество элементов с помощью maxItems:, проанализировать объект до определенной глубины с помощью maxDepth: и изменить отступ печатных объектов с помощью indent:.

71
ayaio

Свифт 3

Приведение словаря к AnyObject было для меня самым простым решением:

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

enter image description here

Для меня это легче читать, чем параметр dump, но учтите, что он не даст вам общее количество значений ключа.

63
Jalakoo

по решению

Для тех из вас, кто хочет видеть Dictionary как JSON без escape-последовательности в console, вот простой способ сделать это

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

57
Irshad Mohamed

Просто еще один способ использования функционального программирования

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

Результат

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

Только для целей отладки я конвертирую Array или Dictionary в симпатичный печатный json:

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

Затем:

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

Результат на консоли:

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

Я бы не стал рассматривать многие ответы, представленные здесь, в истинно симпатичном печатном формате JSON, так как при передаче результатов в валидатор JSON результат является недействительным (часто из-за кода, включающего "=", а не ":").

Я нашел самый простой способ сделать это - просто преобразовать объект JSON в данные, используя довольно печатную опцию записи, а затем распечатать строку, используя полученные данные.

Вот пример:

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

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

Результат:

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

EDIT: Было отмечено, что OP не запрашивал JSON, однако я нахожу, что ответы, которые рекомендуют просто печатать или выгружать данные в консоль, обеспечивают очень небольшое форматирование (если есть) и поэтому не красивые печати.

Я считаю, что, несмотря на то, что OP не запрашивает JSON, это жизнеспособный ответ, так как это гораздо более читаемый формат для данных, чем ужасающий формат, который выплевывает в консоль с помощью xcode/Swift.

6
James Wolfe

Вы можете просто использовать цикл for и печатать каждую итерацию

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

Применение в расширении:

extension Dictionary where Key: CustomDebugStringConvertible, Value:CustomDebugStringConvertible {

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

        return self.description
    }
}

Альтернативное применение:

extension Dictionary where Key: CustomDebugStringConvertible, Value:CustomDebugStringConvertible {

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

Использование:

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

Выход (протестировано в Xcode 8 beta 2 Playground):

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

Для Swift (и опираясь на блестящий ответ @ Jalakoo), сделайте следующее расширение Dictionary:

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

затем напечатайте словарь любая иерархиядовольно способом (лучше, чем dump()), используя это:

print(dictionary!.prettyPrint)
4
AbdelHady

Методология преобразования словаря Swift в json и обратно является самой удобной. Я обычно использую Facebook долото , у которого есть команда pjson , чтобы напечатать словарь Swift. Например:

(lldb) pjson dict as NSDictionary

Это должно красиво распечатать словарь. Это гораздо более чистый способ сделать то, что уже было предложено. Постскриптум На данный момент вам придется использовать dict как NSDictionary, поскольку среда выполнения Objective C не понимает словари Swift. Я уже поднял пиар на долоте, чтобы избавиться от этого ограничения.

2
jarora

Как насчет:

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

Подробности

  • Xcode 10.2.1 (10E1001), Swift 5

Решение

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

Использование

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

Результаты

enter image description here

0
Vasily Bodnarchuk