使用 JSONEncoder 对具有 Codable 作为类型的变量进行编码



我设法让JSON和plist编码和解码工作,但只能通过直接调用特定对象的编码/解码函数。

例如:

struct Test: Codable {
var someString: String?
}
let testItem = Test()
testItem.someString = "abc"
let result = try JSONEncoder().encode(testItem)

这工作得很好,没有问题。

但是,我正在尝试获取一个函数,该函数仅将Codable协议一致性作为类型并保存该对象。

func saveObject(_ object: Encodable, at location: String) {
// Some code
let data = try JSONEncoder().encode(object)
// Some more code
}

这会导致以下错误:

无法使用类型为"(可编码("的参数列表调用"编码">

看看编码函数的定义,好像它应该能够接受Encodable,除非Value是我不知道的奇怪类型。

open func encode<Value>(_ value: Value) throws -> Data where Value : Encodable

使用约束为Encodable的泛型类型

func saveObject<T : Encodable>(_ object: T, at location: String) {
//Some code
let data = try JSONEncoder().encode(object)
//Some more code
}

我会使用不同的方法来扩展具有您可能需要的所有实例方法的可编码协议。在此基础上,您可以向方法添加一个参数来传递自定义编码器,并为所有这些方法提供默认编码器:

extension DataProtocol {
var string: String? { String(bytes: self, encoding: .utf8) }
}

extension Encodable {
func data(using encoder: JSONEncoder = JSONEncoder()) throws -> Data { try encoder.encode(self) }
func string(using encoder: JSONEncoder = JSONEncoder()) throws -> String { try data(using: encoder).string ?? "" }
}

用法

let message = ["key":["a","b","c"]]
let jsonData = try! message.data() // 21 bytes [123, 34, 107, 101, 121, 34, 58, 91, 34, 97, 34, 44, 34, 98, 34, 44, 34, 99, 34, 93, 125]
let jsonString = try! message.string()  // "{"key":["a","b","c"]}"

使用默认编码器传递日期时的示例。请注意,使用的日期编码策略是默认值(双精度表示 timeIntervalSinceReferenceDate(:

let message = ["createdAt": Date()]
let jsonData = try! message.data() // 33 bytes -> [123, 34, 99, 114, 101, 97, 116, 101, 97, 100, 65, 116, 34, 58, 53, 55, 49, 54, 49, 55, 56, 52, 49, 46, 52, 53, 48, 55, 52, 52, 48, 51, 125]
let jsonString = try! message.string()  // {"createdAt":571617841.45074403}"

现在,您可以将自定义编码器传递给您的方法,以人类可读的格式设置日期格式:

let message = ["createdAt": Date()]
let encoder = JSONEncoder()
encoder.dateEncodingStrategy = .iso8601
let jsonString = try! message.string(using: encoder)  // "{"createdAt":"2019-02-11T22:48:19Z"}"

现在使用自定义消息结构

struct Message: Codable {
let id: Int
let createdAt: Date
let sender, title, body: String
}

extension Encodable {
func sendDataToServer(using encoder: JSONEncoder = JSONEncoder()) throws {
print(self, terminator: "nn")
// Don't handle the error here. Propagate the error.
let data = try self.data(using: encoder)
print(data.string!)
// following the code to upload the data to the server
print("Message was successfully sent")
}
}

let message = Message(id: 1, createdAt: Date(), sender: "user@company.com", title: "Lorem Ipsum", body: """
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
""")

let iso8601 = JSONEncoder()
iso8601.dateEncodingStrategy = .iso8601
iso8601.outputFormatting = .prettyPrinted
do {
try message.sendDataToServer(using: iso8601)
} catch {
// handle all errors
print(error)
}

这将打印

Message(id: 1, createdAt: 2019-02-11 23:57:31 +0000, sender: "user@company.com", title: "Lorem Ipsum", body: "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.")
{
"body" : "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.",
"id" : 1,
"sender" : "user@company.com",
"title" : "Lorem Ipsum",
"createdAt" : "2019-02-11T23:57:31Z"
}
now just add the code to send the json data to the server

您需要将泛型函数与泛型类型一起使用Encodable

你不能

func toData(object: Encodable) throws -> Data {
let encoder = JSONEncoder()
return try encoder.encode(object) // Cannot invoke 'encode' with an argument list of type '(Encodable)'
}

您可以

func toData<T: Encodable>(object: T) throws -> Data {
let encoder = JSONEncoder()
return try encoder.encode(object)
}

相关内容

  • 没有找到相关文章

最新更新