簡體   English   中英

如何輕松查看符合“Codable”協議的對象的 JSON 輸出

[英]How can I easily see the JSON output from my objects that conform to the `Codable` Protocol

我處理許多使用 Codable 協議序列化/反序列化為 JSON 的對象。

這並不是努力創造一個JSONEncoder ,設置它漂亮地打印,將對象轉換為JSON,然后將其轉換成一個字符串,但似乎很多工作。 有沒有一種簡單的方法可以說“請給我看看這個對象的 JSON 輸出?”

編輯:

例如說我有以下結構:

struct Foo: Codable {
    let string1: String?
    let string2: String?
    let date: Date
    let val: Int
    let aBar: Bar
}

struct Bar: Codable {
    let name: String
}

並說我創建了一個Foo對象:

let aBar = Bar(name: "Fred")
let aFoo = Foo(string1: "string1", string2: "string2", date: Date(), val: 42, aBar: aBar)

我可以用六行自定義代碼打印出來:

let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
guard let data = try? encoder.encode(aFoo),
    let output = String(data: data, encoding: .utf8)
    else { fatalError( "Error converting \(aFoo) to JSON string") }
print("JSON string = \(output)")

這將給出輸出:

JSON string = {
  "date" : 557547327.56354201,
  "aBar" : {
    "name" : "Fred"
  },
  "string1" : "string1",
  "val" : 42,
  "string2" : "string2"
}

我厭倦了每次需要時編寫相同的六行代碼。 有更容易的方法嗎?

我建議創建一個靜態編碼器,這樣您就不會在每次調用該屬性時都創建一個新的編碼器:

extension JSONEncoder {
    static let shared = JSONEncoder()
    static let iso8601 = JSONEncoder(dateEncodingStrategy: .iso8601)
    static let iso8601PrettyPrinted = JSONEncoder(dateEncodingStrategy: .iso8601, outputFormatting: .prettyPrinted)
}

extension JSONEncoder {    
    convenience init(dateEncodingStrategy: DateEncodingStrategy,
                         outputFormatting: OutputFormatting = [],
                      keyEncodingStrategy: KeyEncodingStrategy = .useDefaultKeys) {
        self.init()
        self.dateEncodingStrategy = dateEncodingStrategy
        self.outputFormatting = outputFormatting
        self.keyEncodingStrategy = keyEncodingStrategy
    }
}

考慮到您是在 Encodable 擴展中調用此方法,您可以強制嘗試!。 您還可以強制從數據轉換為字符串:

extension Encodable {
    func data(using encoder: JSONEncoder = .iso8601) throws -> Data {
        try encoder.encode(self)
    }
    func dataPrettyPrinted() throws -> Data {
        try JSONEncoder.iso8601PrettyPrinted.encode(self)
    }
    // edit if you need the data using a custom date formatter
    func dataDateFormatted(with dateFormatter: DateFormatter) throws -> Data {
        JSONEncoder.shared.dateEncodingStrategy = .formatted(dateFormatter)
        return try JSONEncoder.shared.encode(self)
    }
    func json() throws -> String {
         String(data: try data(), encoding: .utf8) ?? ""
    }
    func jsonPrettyPrinted() throws -> String {
        String(data: try dataPrettyPrinted(), encoding: .utf8) ?? ""
    }
    func jsonDateFormatted(with dateFormatter: DateFormatter) throws -> String {
        return String(data: try dataDateFormatted(with: dateFormatter), encoding: .utf8) ?? ""
    }
}

游樂場測試

struct Foo: Codable {
    let string1: String
    let string2: String
    let date: Date
    let val: Int
    let bar: Bar
}
struct Bar: Codable {
    let name: String
}

let bar = Bar(name: "Fred")
let foo = Foo(string1: "string1", string2: "string2", date: Date(), val: 42, bar: bar)

try! print("JSON\n=================\n", foo.json(), terminator: "\n\n")
try! print("JSONPrettyPrinted\n=================\n", foo.jsonPrettyPrinted(), terminator: "\n\n")
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .long
try! print("JSONDateFormatted\n=================\n", foo.jsonDateFormatted(with: dateFormatter))

這將打印

JSON
==================
{"date":"2020-11-06T20:22:55Z","bar":{"name":"Fred"},"string1":"string1","val":42,"string2":"字符串 2"}

JSONPrettyPrinted
==================
{
"日期": "2020-11-06T20:22:55Z",
“酒吧” : {
“姓名”:“弗雷德”
},
"string1" : "string1",
“瓦爾”:42,
“字符串2”:“字符串2”
}

JSONDateFormatted
==================
{"date":"6 November 2020","bar":{"name":"Fred"},"string1":"string1","val":42,"string2":"string2"}

沒有將Codable對象圖轉換為“漂亮” JSON 字符串的Codable方法,但是定義一個協議來執行此操作非常容易,因此您不必一遍又一遍地編寫相同的轉換代碼。

您可以簡單地為Encodable協議創建一個擴展,如下所示:

extension Encodable {
    var prettyJSON: String {
        let encoder = JSONEncoder()
        encoder.outputFormatting = .prettyPrinted
        guard let data = try? encoder.encode(self),
            let output = String(data: data, encoding: .utf8)
            else { return "Error converting \(self) to JSON string" }
        return output
    }
}

然后對於任何 JSON 對象

print(myJSONobject.prettyJSON)

它以“漂亮的打印”形式顯示 JSON 文本。

上面不會做的一件事是支持日期的自定義格式。 為此,我們可以將 prettyJSON 修改為一個函數而不是一個計算屬性,它接受一個可選的 DateFormatter 作為參數,默認值為nil

extension Encodable {
    func prettyJSON(formatter: DateFormatter? = nil) -> String {
        let encoder = JSONEncoder()
        if let formatter = formatter {
            encoder.dateEncodingStrategy = .formatted(formatter)
        }
        encoder.outputFormatting = .prettyPrinted
        guard let data = try? encoder.encode(self),
            let output = String(data: data, encoding: .utf8)
            else { return "Error converting \(self) to JSON string" }
        return output
    }
}

然后就可以像上面一樣使用了,只不過需要在prettyJSON后面加括號,例如

print(myJSONobject.prettyJSON())

該表單會忽略新的DateFormatter參數,並將輸出與上述相同的 JSON 字符串。 但是,如果您有自定義日期格式化程序:

var formatter = DateFormatter()
formatter.dateFormat = "MM-dd-yyyy HH:mm:ss"

print(myJSONobject.prettyJSON(formatter: formatter))

然后對象圖中的日期將使用指定的 DateFormatter 進行格式化

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM