Có cách nào để in từ điển Swift vào bảng điều khiển không?


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

in ra những điều sau trên bảng điều khiển:

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

in ra những điều sau trên bảng điều khiển:

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

Có cách nào trong Swift để đưa nó vào các từ điển in đẹp mà mỗi cặp khóa-giá trị chiếm một dòng mới không?


7
dumpVí dụ, bạn có thể sử dụng nếu mục đích là kiểm tra từ điển. stackoverflow.com/documentation/swift/3966/logging-in-swift/…
Eric Aya

13
print(dictionary as! NSDictionary) lừa rẻ?
BaseZen

Tôi thực sự là gợi ý dump () vì nó không yêu cầu viết bất kỳ mã nào hoặc ép kiểu. @EricAya, nếu bạn đăng câu trả lời với nhận xét đó, tôi sẽ đánh dấu đó là câu trả lời.
Toland Hon

1
@TolandHon Đã xong. Tôi đã đưa ra câu trả lời với một ví dụ về đầu ra.
Eric Aya

Câu trả lời:


99

Ví dụ, bạn có thể sử dụng kết xuất nếu mục đích là kiểm tra từ điển. dumplà một phần của thư viện tiêu chuẩn của Swift.

Sử dụng:

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

dump(dictionary)

Đầu ra:

nhập mô tả hình ảnh ở đây


dump in nội dung của một đối tượng thông qua phản chiếu (phản chiếu).

Chế độ xem chi tiết của một mảng:

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

Bản in:

▿ 4 phần tử
- [0]: Joe
- [1]: Jane
- [2]: Jim
- [3]: Joyce

Đối với từ điển:

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

Bản in:

▿ 3 cặp khóa / giá trị
▿ [0]: (2 phần tử)
- .0: bar
- .1: 33
▿ [1]: (2 phần tử)
- .0: baz
- .1: 42
▿ [2]: ( 2 phần tử)
- .0: foo
- .1: 10

dumpđược khai báo là dump(_:name:indent:maxDepth:maxItems:).

Tham số đầu tiên không có nhãn.

Có sẵn các thông số khác, chẳng hạn như nameđặt nhãn cho đối tượng đang được kiểm tra:

dump(attributes, name: "mirroring")

Bản in:

▿ phản chiếu: 3 cặp khóa / giá trị
▿ [0]: (2 phần tử)
- .0: bar
- .1: 33
▿ [1]: (2 phần tử)
- .0: baz
- .1: 42
▿ [2] : (2 phần tử)
- .0: foo
- .1: 10

Bạn cũng có thể chọn chỉ in một số mục nhất định với maxItems:, để phân tích cú pháp đối tượng đến một độ sâu nhất định với maxDepth:và thay đổi thụt lề của các đối tượng được in với indent:.


5
Đây không phải là JSON được in đẹp, đây chỉ là kết xuất biến aa vào bảng điều khiển - JSON không hợp lệ. Mặc dù nó phù hợp với nhu cầu của OP, tôi tin rằng câu hỏi cần được ghi lại để phù hợp với điều này.
James Wolfe

4
@JamesWolfe This is not pretty printed JSONKhông ai nói là như vậy. OP đã hỏi về các từ điển Swift in ấn khá đẹp - không ai nói về JSON, ngoại trừ một số người trả lời lạc đề. Câu hỏi của OP hoàn toàn không phải về JSON.
Eric Aya

@JamesWolfe Cũng vui lòng không thay đổi câu hỏi. Đó sẽ là sự phá hoại. Câu hỏi rõ ràng như nó là, và nó không phải về JSON. Đừng thay đổi câu hỏi chỉ vì một số câu trả lời nói về điều khác. Cảm ơn.
Eric Aya

112

Truyền từ điển sang 'AnyObject' là giải pháp đơn giản nhất đối với tôi:

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

đây là đầu ra của bảng điều khiển

Đối với tôi, tùy chọn này dễ đọc hơn tùy chọn kết xuất, nhưng lưu ý rằng nó sẽ không cung cấp cho bạn tổng số khóa-giá trị.


11
Đó là một cách tuyệt vời và cách tốt hơn so với bãi
AbdelHady

109

giải pháp po

Đối với những người bạn muốn xem Từ điển dưới dạng JSON không có trình tự thoát trong bảng điều khiển , đây là một cách đơn giản để làm điều đó

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


1
Vì là một biểu thức chứ không phải một đối tượng, nó phải là 'p' chứ không phải 'po'. Nhưng cảm ơn rất nhiều cho giải pháp này! Hoạt động tốt đối với tôi
Alessandro Francucci

@AlessandroFrancucci có vấn đề gì không? Lệnh này dường như cũng làm điều tương tự.
nickjwallin

Bây giờ cả hai cách làm điều đó đang hoạt động. Nhưng trước khi thực hiện một "po print" không làm việc cho tôi. (phương tiện po in đối tượng .... đó là một chút bối rối nếu bạn có một bản in sau đó và không phải là một đối tượng IMHO)
Alessandro Francucci

Tuyệt vời! chỉ những gì tôi cần để in một cách đẹp mắt userInfo từ PushNotification
carmen_munich

Kiểm tra nhận xét này để tận dụng điều này trong bí danh lldb để bạn không phải gõ nó mọi lúc!
agirault

36

Chỉ là một cách khác bằng cách sử dụng Lập trình chức năng

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

Đầu ra

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

1
Đây phải là câu trả lời hàng đầu. Hoạt động hoàn hảo!
Yuri Doubov

Hoặc là "thậm chí thêm chức năng" ... dictionary.map { "($ 0): ($ 1)"} .forEach (in) (lưỡi-in-cheek bình luận)
Jon Willis

3
Điều này hoạt động với [String: String]từ điển của OP , nhưng nó không tốt cho [AnyHashable: Any]từ điển, trong đó nếu một giá trị là một từ điển, bạn sẽ quay lại việc in ấn không đẹp của Swift.
Christopher Pickslay

Tôi có cuốn sách đánh dấu answer🙂 này, bởi vì tôi vẫn không thể nhớ cú pháp này 🙄
Nitin Alabur

29

Chỉ với mục đích gỡ lỗi, tôi sẽ chuyển đổi Mảng hoặc Từ điển thành một json in đẹp:

public extension Collection {

    /// Convert self to JSON String.
    /// Returns: the pretty printed JSON string or an empty string if any error occur.
    func json() -> String {
        do {
            let jsonData = try JSONSerialization.data(withJSONObject: self, options: [.prettyPrinted])
            return String(data: jsonData, encoding: .utf8) ?? "{}"
        } catch {
            print("json serialization error: \(error)")
            return "{}"
        }
    }
}

Sau đó:

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

Kết quả trên bảng điều khiển:

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

bLog ở đây là gì?
Nitesh

@Nitesh bLog là một trình ghi nhật ký tùy chỉnh đơn giản với backtrace mà tôi đã viết, được chỉnh sửa bằng print ().
Marco M

Giải pháp đẹp nhất.
Denis Kutlubaev

Nếu bạn muốn tránh thêm đoạn mã đó trong mỗi dự án của mình, bạn có thể tận dụng đoạn mã đó với bí danh lldb để dễ dàng tính toán json trong thiết bị đầu cuối gỡ lỗi (chi tiết tại đây ).
agirault

14

Tôi sẽ không xem xét nhiều câu trả lời được cung cấp ở đây là JSON in khá đẹp, vì khi bạn chuyển kết quả vào trình xác thực JSON, kết quả không hợp lệ (thường do mã bao gồm '=' thay vì ':').

Cách dễ nhất mà tôi đã tìm thấy để thực hiện việc này chỉ là chuyển đổi đối tượng JSON thành dữ liệu bằng cách sử dụng tùy chọn viết in đẹp, sau đó in một chuỗi bằng dữ liệu kết quả.

Đây là một ví dụ:

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

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

Kết quả:

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

CHỈNH SỬA : Người ta đã chỉ ra rằng OP không yêu cầu JSON, tuy nhiên tôi thấy rằng các câu trả lời khuyến nghị chỉ in hoặc kết xuất dữ liệu vào bảng điều khiển cung cấp rất ít định dạng (nếu có) và do đó in không đẹp.

Tôi tin rằng mặc dù OP không yêu cầu JSON, đó là một câu trả lời khả thi vì nó là một định dạng dữ liệu dễ đọc hơn nhiều so với định dạng khủng khiếp được phun ra vào bảng điều khiển bằng xcode / swift.


1
Cảm ơn, Với tôi đây đã có thể in khá trong bối cảnh gỡ lỗi qua e let jsonData = try! JSONSerialization.data(withJSONObject: response, options: .prettyPrinted);if let jsonString = String(data: jsonData, encoding: .utf8) { print(jsonString) }
BangOperator

1
Điều đó thật tuyệt! Bạn có thể tận dụng mã này với bí danh lldb để dễ dàng tính toán json trong thiết bị đầu cuối gỡ lỗi (chi tiết tại đây ).
agirault

5

Bạn chỉ có thể sử dụng vòng lặp for và in mỗi lần lặp lại

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

Ứng dụng trong phần mở rộng:

extension Dictionary where Key: CustomDebugStringConvertible, Value:CustomDebugStringConvertible {

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

        return self.description
    }
}

Ứng dụng thay thế:

extension Dictionary where Key: CustomDebugStringConvertible, Value:CustomDebugStringConvertible {

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

Sử dụng:

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

Đầu ra (Đã thử nghiệm trong Sân chơi Xcode 8 beta 2):

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

1
Có lý do gì khiến bạn tạo prettyprint một var thay vì chỉ một hàm không?
Hayden Holligan

Thành thật mà nói, tôi không nghĩ nó quan trọng (tôi có thể sai). Nhưng nếu bạn sử dụng nó nhiều thì bạn sẽ ít gõ hơn. Nhưng hãy nêu ra một câu hỏi thú vị.
Asdrubal

3
Vì đã có descriptiondebugDescriptionnên gọi var prettyDescriptionvà trả về chuỗi được định dạng sẽ thích hợp hơn .
Toland Hon

5

Phương pháp chuyển đổi Từ điển Swift sang json và ngược lại là phương pháp gọn gàng nhất. Tôi sử dụng cái đục của Facebook có lệnh pjson để in từ điển Swift. Ví dụ:

(lldb) pjson dict as NSDictionary

Điều này nên in từ điển. Đây là một cách dễ dàng hơn nhiều để thực hiện những gì đã được đề xuất. PS Hiện tại, bạn sẽ phải truyền dict là NSDictionary vì thời gian chạy Objective-C không hiểu từ điển Swift. Tôi đã tăng cường PR về sự đục khoét để thoát khỏi hạn chế đó.

CẬP NHẬT: Bài PR của tôi đã được chấp nhận. Bây giờ bạn có thể sử dụng lệnh psjson thay vì pjson đã đề cập ở trên.


4

Đối với Swift 3 (& xây dựng dựa trên câu trả lời tuyệt vời của @Jalakoo ), hãy tạo Dictionaryphần mở rộng sau :

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

sau đó in một cuốn từ điển của bất kỳ hệ thống cấp bậc trong một khá cách (tốt hơn dump()) sử dụng này:

print(dictionary!.prettyPrint)

4

Chi tiết

  • Xcode 10.2.1 (10E1001), Swift 5

Giải pháp

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

Sử dụng

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

Các kết quả

nhập mô tả hình ảnh ở đây


2

Điều chỉnh dựa trên câu trả lời khác của tôi ở đây .

Giải pháp PrettyPrint JSON sử dụng bí danh LLDB

Không cần mã

  • Để có định dạng json đẹp (thụt lề, dòng mới, v.v.), bạn có thể xác định bí danh lldb bằng cách chạy lệnh này trong thiết bị đầu cuối lldb của bạn ( nguồn ):
command regex pjson 's/(.+)/expr print(NSString(string: String(data: try! JSONSerialization.data(withJSONObject: %1, options: .prettyPrinted), encoding: .utf8)!))/'
  • Bạn có thể không muốn xác định lại bí danh mỗi khi bạn mở XCode, vì vậy hãy chạy lệnh sau để thêm định nghĩa bí danh vào ~/.lldbinit:
echo "command regex pjson 's/(.+)/expr print(NSString(string: String(data: try! JSONSerialization.data(withJSONObject: %1, options: .prettyPrinted), encoding: .utf8)!))/'" >> ~/.lldbinit
  • Thao tác này sẽ tạo pjsonbí danh mà bạn có thể sử dụng trong thiết bị đầu cuối lldb của mình trong XCode:
pjson object

So sánh kết quả đầu ra cho đối tượng Swift sau:

// Using Any? to demo optional & arbitrary Type
let dictionary: Any? = [
    "embedded": [
        "JustForTheSakeOfTheDemo": 42
    ],
    "A" : "alfa",
    "B" : "bravo",
    "C" : "charlie",
    "D" : "delta",
    "E" : "echo",
    "F" : "foxtrot"
]

✅ Đầu ra của pjson dictionary

{
  "F" : "foxtrot",
  "D" : "delta",
  "embedded" : {
    "JustForTheSakeOfTheDemo" : 42
  },
  "E" : "echo",
  "A" : "alfa",
  "C" : "charlie",
  "B" : "bravo"
}

❌ Sản lượng của p dictionary

(Any?) $R0 = 7 key/value pairs {
  [0] = {
    key = "F"
    value = "foxtrot"
  }
  [1] = {
    key = "D"
    value = "delta"
  }
  [2] = {
    key = "embedded"
    value = 1 key/value pair {
      [0] = (key = "JustForTheSakeOfTheDemo", value = 42)
    }
  }
  [3] = {
    key = "E"
    value = "echo"
  }
  [4] = {
    key = "A"
    value = "alfa"
  }
  [5] = {
    key = "C"
    value = "charlie"
  }
  [6] = {
    key = "B"
    value = "bravo"
  }
}

❌ Sản lượng của p (dictionary as! NSDictionary)

(NSDictionary) $R18 = 0x0000000281e89710 {
  ObjectiveC.NSObject = {
    base__SwiftNativeNSDictionaryBase@0 = {
      baseNSDictionary@0 = {
        NSObject = {
          isa = Swift._SwiftDeferredNSDictionary<Swift.String, Any> with unmangled suffix "$"
        }
      }
    }
  }
}

❌ Sản lượng của po dictionary

Optional<Any>
  ▿ some : 7 elements
    ▿ 0 : 2 elements
      - key : "F"
      - value : "foxtrot"1 : 2 elements
      - key : "D"
      - value : "delta"2 : 2 elements
      - key : "embedded"
      ▿ value : 1 element
        ▿ 0 : 2 elements
          - key : "JustForTheSakeOfTheDemo"
          - value : 423 : 2 elements
      - key : "E"
      - value : "echo"4 : 2 elements
      - key : "A"
      - value : "alfa"5 : 2 elements
      - key : "C"
      - value : "charlie"6 : 2 elements
      - key : "B"
      - value : "bravo"

❌ Sản lượng của po print(dictionary)

Optional(["F": "foxtrot", "D": "delta", "embedded": ["JustForTheSakeOfTheDemo": 42], "E": "echo", "A": "alfa", "C": "charlie", "B": "bravo"])


1

Khi gỡ lỗi, hãy xuất cấu trúc phù hợp với Giao thức có thể mã hóa sang bảng điều khiển
sử dụng định dạng json.

extension Encodable {
    var jsonData: Data? {
        let encoder = JSONEncoder()
        encoder.outputFormatting = .prettyPrinted
        return try? encoder.encode(self)
    }
}

extension Encodable where Self: CustomDebugStringConvertible {
    var debugDescription: String {
         if let data = self.jsonData,
             let string = String(data: data, encoding: .utf8) {
             return string
         }
         return "can not convert to json string"
     }
}

strcut phù hợp CustomDebugStringConvertible

struct Test: Codable, CustomDebugStringConvertible {
    let a: String
    let b: Int
}

let t = Test(a: "test string", b: 30)

gỡ lỗi cấu trúc in

(lldb) p print(t)
{
  "a" : "test string",
  "b" : 30
}

1

Bản in đẹp từ đối tượng Dữ liệu:

let jsonObj = try JSONSerialization.jsonObject(with: data, options: [])
            let jsonData = try JSONSerialization.data(withJSONObject: jsonObj, options: [.prettyPrinted])
            print(String(data: jsonData, encoding: .utf8)!)

1
Điều đó thật tuyệt! Bạn có thể tận dụng mã này với bí danh lldb để dễ dàng tính toán json trong thiết bị đầu cuối gỡ lỗi (chi tiết tại đây ).
agirault

0

Làm thế nào về:

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
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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.