Reputation: 834
I want to set up a remote configuration file for staged feature releases, seasonal changes, offers etc. that wouldn't be worth going through App Review for.
I used to use a \n
separated text file but for multi-line strings this gets a bit awkward real quick.
Instead of importing some bloated framework like Firebase for this, I am currently writing a small singleton that parses a configuration file from a remote URL.
I am however facing one issue now:
If the remote json contains a key that's not defined in my Codable struct everything works fine, I still get my object with all the defined keys. Not so much the other way around, if the json is missing a key defined in the struct, JSONDecoder is not able to decode. Example:
let testJSON = """
{"version":1,"includedB":"B","___notIncludedC":"C"}
"""
struct DefaultConfiguration : Codable {
var version = 1
var includedB = "2"
var notIncludedC = "3"
}
I can make the decoding """work""" by defining the notIncludedC to be of an optional String?
- this however makes the result be nil
after decoding instead of keeping its predefined default value.
All the answers on SO mention defining custom methods for each key, but I would rather like to use a "skip unknown and keep the value" approach because for big JSON's that would come with a lot of overhead code.
Upvotes: 6
Views: 1644
Reputation: 1688
As a it was described in the comments you will have to write your own init() since the synthesized one can not provide the behavior you need:
let testJSON = """
{"version":1,"includedB":"B","notIncludedC":"C"}
"""
struct DefaultConfiguration : Codable {
var version = 1
var includedB = "2"
var notIncludedC = "3"
enum CodingKeys: String, CodingKey {
case version
case includedB
case notIncludedC
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
version = try container.decode(Int.self, forKey: .version)
includedB = try container.decode(String.self, forKey: .includedB)
notIncludedC = try container.decodeIfPresent(String.self, forKey: .notIncludedC) ?? "3"
}
}
Upvotes: 7