我处理了许多使用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"
}
每当需要时,我都厌倦了编写相同的六行代码。有没有更简单的方法?
答案 0 :(得分:2)
我建议您创建一个静态编码器,这样您就不必在每次调用该属性时都创建一个新的编码器:
extension JSONEncoder {
static let shared = JSONEncoder()
static let iso8601 = JSONEncoder(dateEncodingStrategy: .iso8601)
static let iso8601PrittyPrinted = JSONEncoder(dateEncodingStrategy: .iso8601, outputFormatting: .prettyPrinted)
convenience init(dateEncodingStrategy: DateEncodingStrategy, outputFormatting: OutputFormatting? = nil) {
self.init()
self.dateEncodingStrategy = dateEncodingStrategy
self.outputFormatting = outputFormatting ?? []
}
}
考虑到您正在Encodable扩展中调用此方法,您可以强制尝试!您还可以强制将数据转换为字符串:
extension Encodable {
var data: Data {
return try! JSONEncoder.iso8601.encode(self)
}
var dataPrettyPrinted: Data {
return try! JSONEncoder.iso8601PrittyPrinted.encode(self)
}
// edit if you need the data using a custom date formatter
func dataDateFormatted(with dateFormatter: DateFormatter) -> Data {
JSONEncoder.shared.dateEncodingStrategy = .formatted(dateFormatter)
return try! JSONEncoder.shared.encode(self)
}
var json: String {
return String(data: data, encoding: .utf8)!
}
var jsonPrettyPrinted: String {
return String(data: dataPrettyPrinted, encoding: .utf8)!
}
func jsonDateFormatted(with dateFormatter: DateFormatter) -> String {
return String(data: 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)
print("json\n====\n\n", foo.json)
print()
print("jsonPrettyPrinted\n=================\n\n", foo.jsonPrettyPrinted)
print()
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .long
print("jsonDateFormatted\n=================\n\n", foo.jsonDateFormatted(with: dateFormatter))
这将打印
/*
json
====
{"date":"2018-09-02T15:35:37Z","bar":{"name":"Fred"},"string1":"string1","val":42,"string2":"string2"}
jsonPrettyPrinted
=================
{
"date" : "2018-09-02T15:35:37Z",
"bar" : {
"name" : "Fred"
},
"string1" : "string1",
"val" : 42,
"string2" : "string2"
}
jsonDateFormatted
=================
{"date":"September 2, 2018","bar":{"name":"Fred"},"string1":"string1","val":42,"string2":"string2"}
*/
答案 1 :(得分:1)
没有将Codable
对象图转换为“漂亮的” JSON字符串的常用方法,但是定义协议很容易做到这一点,因此您不必在上面编写相同的转换代码以上。
您可以简单地为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格式化对象图中的日期