Is there a way to pretty print Swift dictionaries to the console?

前端 未结 16 935
北海茫月
北海茫月 2020-12-07 09:33
NSDictionary *dictionary = @{@\"A\" : @\"alfa\",
                             @\"B\" : @\"bravo\",
                             @\"C\" : @\"charlie\",
                       


        
相关标签:
16条回答
  • 2020-12-07 10:14

    How about:

    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 讨论(0)
  • 2020-12-07 10:15

    I wouldn't consider a lot of the answers provided here true pretty printed JSON, as when you pass the results into a JSON validator the result is invalid (often due to the code including '=' rather than ':').

    The easiest way I've found of doing this is just converting the JSON object to data using the pretty printed writing option then printing a string using the resulting data.

    Here is an example:

    let jsonData = try! JSONSerialization.data(withJSONObject: parameters, options: .prettyPrinted)
    
    if let jsonString = String(data: jsonData, encoding: .utf8) {
        print(jsonString)
    }
    

    Result:

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

    EDIT: It's been pointed out that the OP did not ask for JSON, however I find that the answers that recommend just printing or dumping the data into the console provide very little formatting (if any) and are therefore not pretty printing.

    I believe that despite the OP not asking for JSON, it is a viable answer as it is a much more readable format for data than the horrendous format that is spat out into the console by xcode/swift.

    0 讨论(0)
  • You could use dump, for example, if the goal is to inspect the dictionary. dump is part of Swift's standard library.

    Usage:

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

    Output:


    dump prints the contents of an object via reflection (mirroring).

    Detailed view of an array:

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

    Prints:

    ▿ 4 elements
    - [0]: Joe
    - [1]: Jane
    - [2]: Jim
    - [3]: Joyce

    For a dictionary:

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

    Prints:

    ▿ 3 key/value pairs
    ▿ [0]: (2 elements)
    - .0: bar
    - .1: 33
    ▿ [1]: (2 elements)
    - .0: baz
    - .1: 42
    ▿ [2]: (2 elements)
    - .0: foo
    - .1: 10

    dump is declared as dump(_:name:indent:maxDepth:maxItems:).

    The first parameter has no label.

    There's other parameters available, like name to set a label for the object being inspected:

    dump(attributes, name: "mirroring")
    

    Prints:

    ▿ mirroring: 3 key/value pairs
    ▿ [0]: (2 elements)
    - .0: bar
    - .1: 33
    ▿ [1]: (2 elements)
    - .0: baz
    - .1: 42
    ▿ [2]: (2 elements)
    - .0: foo
    - .1: 10

    You can also choose to print only a certain number of items with maxItems:, to parse the object up to a certain depth with maxDepth:, and to change the indentation of printed objects with indent:.

    0 讨论(0)
  • 2020-12-07 10:22

    For Swift 3 (& building on the brilliant answer by @Jalakoo), make the following Dictionary extension:

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

    then print a dictionary of any hierarchy in a pretty way (better than dump()) using this:

    print(dictionary!.prettyPrint)
    
    0 讨论(0)
  • 2020-12-07 10:22

    Adjusted based on my other answer here.

    PrettyPrint JSON solution using LLDB alias

    No code needed

    • To get a nice json formatting (indentations, newlines, etc) you can define an lldb alias by running this command in your lldb terminal (source):
    command regex pjson 's/(.+)/expr print(NSString(string: String(data: try! JSONSerialization.data(withJSONObject: %1, options: .prettyPrinted), encoding: .utf8)!))/'
    
    • You probably don't want to re-define the alias everytime you open XCode, so run the following command to append the alias definition to ~/.lldbinit:
    echo "command regex pjson 's/(.+)/expr print(NSString(string: String(data: try! JSONSerialization.data(withJSONObject: %1, options: .prettyPrinted), encoding: .utf8)!))/'" >> ~/.lldbinit
    
    • This will create the pjson alias which you can use in your lldb terminal in XCode:
    pjson object
    

    Comparing the outputs for the following Swift object:

    // 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"
    ]
    

    ✅ Output of pjson dictionary

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

    ❌ Output of 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"
      }
    }
    

    ❌ Output of p (dictionary as! NSDictionary)

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

    ❌ Output of 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 : 42
        ▿ 3 : 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"
    

    ❌ Output of po print(dictionary)

    Optional(["F": "foxtrot", "D": "delta", "embedded": ["JustForTheSakeOfTheDemo": 42], "E": "echo", "A": "alfa", "C": "charlie", "B": "bravo"])
    
    0 讨论(0)
  • 2020-12-07 10:22

    Pretty print from Data object:

    let jsonObj = try JSONSerialization.jsonObject(with: data, options: [])
                let jsonData = try JSONSerialization.data(withJSONObject: jsonObj, options: [.prettyPrinted])
                print(String(data: jsonData, encoding: .utf8)!)
    
    0 讨论(0)
提交回复
热议问题