Reputation: 733
The API I am using supports multi-language. For instance:
// For Japanese
{
"earthquake_detail": {
"advisory_title_ja": "津波注意報",
"depth_title_ja": "震源深さ",
"depth_value_ja": "30km",
}
}
// For English
{
"earthquake_detail": {
"advisory_title_en": "Tsunami Advisory",
"depth_title_en": "Depth",
"depth_value_en": "30km",
}
}
I am using swift codable to map them to a struct. Is there a way that I can map multiple coding keys to a single variable? Here is my swift struct.
struct EarthquakeDetail: Codable {
var advisoryTitle, depthTitle, depthValue: String?
enum CodingKeys: String, CodingKey {
case advisoryTitle = "advisory_title_ja"
case depthTitle = "depth_title_ja"
case depthValue = "depth_value_ja"
}
}
What I want to obtain is for Japanese this will be the coding keys:
enum CodingKeys: String, CodingKey {
case advisoryTitle = "advisory_title_ja"
case depthTitle = "depth_title_ja"
case depthValue = "depth_value_ja"
}
and for English:
enum CodingKeys: String, CodingKey {
case advisoryTitle = "advisory_title_en"
case depthTitle = "depth_title_en"
case depthValue = "depth_value_en"
}
Upvotes: 1
Views: 784
Reputation: 285069
If you are not going to use the convertFromSnakeCase
strategy add a custom key decoding strategy which drops the _xx
from the three coding keys.
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .custom { codingKeys in
let lastKey = codingKeys.last!
if lastKey.intValue != nil || codingKeys.count != 2 { return lastKey }
if codingKeys.dropLast().last!.stringValue != "earthquake_detail" { return lastKey }
return AnyCodingKey(stringValue: String(lastKey.stringValue.dropLast(3)))!
}
If the earthquake_detail
key is deeper than on level 2 change != 2
accordingly
To be able to create custom coding keys you need
struct AnyCodingKey: CodingKey {
var stringValue: String
var intValue: Int?
init?(stringValue: String) { self.stringValue = stringValue }
init?(intValue: Int) {
self.stringValue = String(intValue)
self.intValue = intValue
}
}
Now declare EarthquakeDetail
as follows
struct EarthquakeDetail: Codable {
var advisoryTitle, depthTitle, depthValue: String
enum CodingKeys: String, CodingKey {
case advisoryTitle = "advisory_title"
case depthTitle = "depth_title"
case depthValue = "depth_value"
}
}
Upvotes: 2