Swift辞書をコンソールにきれいに印刷する方法はありますか?


94
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に、各キーと値のペアが新しい行を占めるプリティプリント辞書を作成する方法はありますか?


8
dumpたとえば、目標が辞書の検査である場合に使用できます。stackoverflow.com/documentation/swift/3966/logging-in-swift/…–
Eric Aya

14
print(dictionary as! NSDictionary) 小細工?
BaseZen 2016

コードを書いたりキャストしたりする必要がないので、私は本当にdump()の提案です。@EricAya、あなたがそのコメントで答えを投稿するならば、私はそれを答えとしてマークします。
Toland Hon

1
@TolandHon完了。出力の例で答えました。
Eric Aya

回答:


102

たとえば、目標が辞書の検査である場合は、ダンプを使用できます。dumpSwiftの標準ライブラリの一部です。

使用法:

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

dump(dictionary)

出力:

ここに画像の説明を入力してください


dump 反射(ミラーリング)を介してオブジェクトの内容を印刷します。

アレイの詳細ビュー:

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

プリント:

▿4要素
-[0]:ジョー
-[1]:ジェーン
-[2]:ジム
-[3]:ジョイス

辞書の場合:

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

プリント:

▿3つのキー/値のペア
▿[0] :( 2要素)
-。0:バー -.1

33▿[1] :( 2要素)
-。0:baz
-.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:baz
-.1:
42▿[2] :( 2要素)
-。0:foo
-.1:10

また、を使用して特定の数のアイテムのみを印刷したりmaxItems:、を使用して特定の深さまでオブジェクトを解析maxDepth:したり、を使用して印刷されたオブジェクトのインデントを変更したりすることもできますindent:


7
これはきれいに印刷されたJSONではありません。これは変数をコンソールにダンプしているだけです-有効なJSONではありません。OPのニーズには合っていますが、これに一致するように質問を言い換える必要があると思います。
ジェームズ・ウルフ

4
@JamesWolfeThis is not pretty printed JSON誰もそうだとは言いませんでした。OPは、Swift辞書のプリティプリントについて質問しました。トピックに関係のない回答者を除いて、JSONについては誰も話していません。OPの質問はJSONに関するものではありません。
エリック・彩

@JamesWolfeまた、質問を変更しないでください。それは破壊行為になります。問題はそれなりに明確であり、JSONに関するものではありません。一部の回答が他のことについて話しているという理由だけで質問を変更しないでください。ありがとう。
エリック・アヤ

113

poソリューション

コンソールにエスケープシーケンスのないJSONとして辞書を見たい人のために、これを行う簡単な方法があります

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

更新

この回答も確認してください回答


1
は式であり、オブジェクトではないため、「po」ではなく「p」である必要があります。しかし、このソリューションに感謝します!私にとっては問題なく動作します
Alessandro Francucci 2018

@AlessandroFrancucciそれは重要ですか?コマンドはどちらの方法でも同じことをするようです。
nickjwallin 2018年

現在、それを行う両方の方法が機能しています。しかし、「poプリント」を行う前は私にはうまくいきませんでした。(poは印刷オブジェクトを意味します....後で印刷し、オブジェクトimhoではない場合は少し混乱します)
Alessandro Francucci 2018年

驚くばかり!私はPushNotificationから良い方法のUserInfoで印刷するために必要なものだけ
carmen_munich

1
このコメントをチェックして、lldbエイリアスでこれを活用すると、毎回入力する必要がなくなります。
agirault

112

辞書を「AnyObject」にキャストすることは、私にとって最も簡単な解決策でした。

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

これはコンソール出力です

これは、ダンプオプションよりも読みやすいですが、キー値の総数が表示されないことに注意してください。


12
それは素晴らしい方法であり、ダンプよりもはるかに優れています
AbdelHady 2018

36

関数型プログラミングを使用する別の方法

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

出力

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

1
これが一番の答えになるはずです。完璧に動作します!
ユーリドゥボフ2017年

または、「さらに機能的に」するために... dictionary.map {"($ 0):($ 1)"} .forEach(print)(tongue-in-cheekコメント)
Jon Willis

3
これはOPの[String: String]辞書で[AnyHashable: Any]は機能しますが、値が辞書である場合はSwiftの見栄えの悪い印刷に戻る辞書には適していません。
Christopher Pickslay 2018

I私はまだ🙄この構文を思い出すことができないので、この本は、このanswer🙂をマークしている
ニティンAlabur

29

デバッグの目的でのみ、配列または辞書をきれいに印刷されたjsonに変換します。

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

次に:

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
}

ここでbLogとは何ですか?
Nitesh 2017

@Nitesh bLogは、print()で編集した、私が作成したバックトレースを備えたシンプルなカスタムロガーです。
マルコM

最も美しいソリューション。
DenisKutlubaev20年

各プロジェクトにそのコードスニペットを追加したくない場合は、そのコードをlldbエイリアスで活用して、デバッグターミナルでjsonを簡単に計算できます(詳細はこちら)。
agirault

14

結果を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"
    }
}

編集:OPがJSONを要求しなかったことが指摘されていますが、データをコンソールに印刷またはダンプすることを推奨する回答では、フォーマットがほとんど提供されないため、きれいに印刷されないことがわかりました。

OPがJSONを要求していないにもかかわらず、xcode / swiftによってコンソールに吐き出される恐ろしい形式よりもはるかに読みやすいデータ形式であるため、実行可能な答えであると私は信じています。


1
おかげで、これで私はデバッグ中にきれいに印刷することができました e let jsonData = try! JSONSerialization.data(withJSONObject: response, options: .prettyPrinted);if let jsonString = String(data: jsonData, encoding: .utf8) { print(jsonString) }
BangOperator 2018年

1
これは素晴らしい!このコードをlldbエイリアスとともに活用して、デバッグ端末でjsonを簡単に計算できます(詳細はこちら)。
agirault

5

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ベータ2プレイグラウンドでテスト済み):

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

1
関数だけでなく、プリティプリントを変数にした理由はありますか?
Hayden Holligan 2016

正直なところ、私はそれが重要だとは思いません(私は間違っている可能性があります)。しかし、それを頻繁に使用する場合は、入力する必要はありません。しかし、興味深い質問を提起します。
Asdrubal 2016

3
descriptionとはdebugDescriptionすでに存在するため、varを呼び出してprettyDescription、フォーマットされた文字列を返す方が適切な場合があります。
Toland Hon

5

Swift辞書をjsonに変換したり、元に戻したりする方法論が最も優れています。私はFacebookの使用ノミありpjsonのスウィフト辞書を印刷するコマンドを。例えば:

(lldb) pjson dict as NSDictionary

これにより、辞書がきれいに印刷されます。これは、すでに提案されていることを実行するためのはるかにクリーンな方法です。PS今のところ、Objective-CランタイムはSwift辞書を理解しないため、dictをNSDictionaryとしてキャストする必要があります。私はすでにその制限を取り除くためにノミのPRを上げました。

更新:私のPRが受け入れられました。今、あなたは使用することができますpsjsonの代わりにコマンドをpjson前述しました。


4

スウィフト3(&によって華麗な答えに構築@Jalakoo)、次のようにするDictionary拡張機能を:

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

次に、これを使用して、任意の階層の辞書をきれいな方法で(より良い方法でdump())印刷します。

print(dictionary!.prettyPrint)

4

詳細

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

結果

ここに画像の説明を入力してください


4

ここで私の他の答えに基づいて調整されました

LLDBエイリアスを使用したPrettyPrintJSONソリューション

コードは必要ありません

  • 優れたjsonフォーマット(インデント、改行など)を取得するには、lldbターミナル(ソース)で次のコマンドを実行して、lldbエイリアスを定義します。
command regex pjson 's/(.+)/expr print(NSString(string: String(data: try! JSONSerialization.data(withJSONObject: %1, options: .prettyPrinted), encoding: .utf8)!))/'
  • XCodeを開くたびにエイリアスを再定義したくない場合は、次のコマンドを実行してエイリアス定義を次のように追加します~/.lldbinit
echo "command regex pjson 's/(.+)/expr print(NSString(string: String(data: try! JSONSerialization.data(withJSONObject: %1, options: .prettyPrinted), encoding: .utf8)!))/'" >> ~/.lldbinit
  • これpjsonにより、XCodeのlldbターミナルで使用できるエイリアスが作成されます。
pjson object

次のSwiftオブジェクトの出力を比較します。

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

✅の出力 pjson dictionary

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

❌の出力 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"
  }
}

❌の出力 p (dictionary as! NSDictionary)

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

❌の出力 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"

❌の出力 po print(dictionary)

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


1

デバッグ時に、CodableProtocolをコンソールに準拠する構造体を
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適合CustomDebugStringConvertible

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

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

デバッグ印刷構造体

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

1

データオブジェクトからのプリティプリント:

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

1
これは素晴らしい!このコードをlldbエイリアスとともに活用して、デバッグ端末でjsonを簡単に計算できます(詳細はこちら)。
agirault

0

どうですか:

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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.