Using Codable to encode/decode from Strings to Ints with a function in between

此生再无相见时 提交于 2020-12-30 04:22:17

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!