I'm decoding a JSON API to a struct, with a CodingKey
enum in order to map the language key from the response to the name
property of the struct:
{
id: "1",
english: "United States",
french: "États Unis",
spanish: "Estados Unidos"
}
struct Country: Codable, Hashable, Identifiable {
let id: String
let name: String
enum CodingKeys : String, CodingKey {
case id
case name = "french"
}
}
I want to be able to control programmatically the assigned name
value in the CodingKeys
enum so it'll be based on the user device locale.
// English user
country.name // "United States"
// French user
country.name // "États Unis"
I have the function getUserLocale()
that checks for the user's locale and returns the string value of it ( english
, french
, etc...).
How can I make it run during the enum initalization so it'll assign the locale value to the name
property?
Implementing custom decoding should work. Here's an example.
let sampleJSON = """
{
"id": "1",
"english": "United States",
"french": "États Unis",
"spanish": "Estados Unidos"
}
"""
var userLocale = "english"
struct Country: Decodable, Hashable, Identifiable {
let id: String
let name: String
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
id = try values.decode(String.self, forKey: .id)
name = try values.decode(String.self, forKey: CodingKeys(rawValue: userLocale)!)
}
enum CodingKeys : String, CodingKey {
case id
case english
case french
case spanish
}
}
let decoder = JSONDecoder()
let country = try decoder.decode(Country.self, from: sampleJSON.data(using: .utf8)!)
debugPrint(country)
userLocale = "french"
let anotherCountry = try decoder.decode(Country.self, from: sampleJSON.data(using: .utf8)!)
debugPrint(anotherCountry)
Regardless of the current language you have to decode the entire JSON anyway.
My suggestion is to add a function to return the localized name.
First create another enum for the supported languages
enum CountryCode : String {
case en, fr, es
}
struct Country: Codable, Hashable, Identifiable {
let id: String
let english, french, spanish : String
func name(for countryCode: CountryCode) -> String {
switch countryCode {
case .en: return english
case .fr: return french
case .es: return spanish
}
}
}
CountryCode
is declared with a raw value to be able to initialize a value from the 2-letter country code.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.