问题
I have this json string:
let json = """
{
"name": "Wendy Carlos",
"hexA": "7AE147AF",
"hexB": "851EB851"
}
"""
let data = Data(json.utf8)
...which I'd like to encode to (and back from) this struct, using Codable:
struct CodeMe: Codable {
var name: String
var hexA: Int
var hexB: Int
enum CodingKeys: String, CodingKey {
case name, hexA, hexB
}
}
let encoder = JSONEncoder()
let decoder = JSONDecoder()
But hexA and hexB are Strings (in the JSON) and I need these to be Ints in the Swift object. I have already written 20 functions for that purpose. e.g. in pseudocode:
func hexAConversion(from hex: String)->Int {
// returns an Int between -50 and 50
}
func hexBConversion(from hex: String)->Int {
// returns an Int between 0 and 360
}
Taking into account that there are a fair few conversion schemes like this and that I need I need write 20 more functions (for the Int->Hexadecimal roundtrip), how would I write a custom decoding and encoding strategy that works with the above?
I've had a look at these solutions: Swift 4 JSON Decodable simplest way to decode type change but my use case seems slightly different, as the accepted answer looks like it deals with a straight type conversion whereas I need to run some functions.
回答1:
For Codable
encoding and decoding that requires custom transformation type stuff, like that, you just need to implement the initializer and encode methods yourself. In your case it would look something like this. It's a bit verbose just to try to get the idea across really clearly.
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.name = try container.decode(String.self, forKey: .name)
let hexAString: String = try container.decode(String.self, forKey: .hexA)
self.hexA = hexAConversion(from: hexAString)
let hexBString: String = try container.decode(String.self, forKey: .hexB)
self.hexB = hexBConversion(from: hexBString)
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
//Assuming you have another set of methods for converting back to a String for encoding
try container.encode(self.name, forKey: .name)
try container.encode(hexAStringConversion(from: self.hexA), forKey: .hexA)
try container.encode(hexBStringConversion(from: self.hexB), forKey: .hexB)
}
来源:https://stackoverflow.com/questions/65314663/using-codable-to-encode-decode-from-strings-to-ints-with-a-function-in-between