7

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.

4
  • You will have to write your own decoding init. The synthesised Decodable conformance won't do what you need, so you will have to write it yourself. It shouldn't take much code to do anyways Commented Nov 27, 2021 at 17:47
  • 1
    Making optional properties optional is the most straightforward solution imo. Commented Nov 27, 2021 at 18:42
  • @JoakimDanielson I was about to move to that solution now but I just found out that then, the property of the struct will be nil instead of the default value. Like I'm okay with optional values now but it still gives me nil then whereas I'd like to simply keep the predefined value. Am I doing something wrong? Commented Dec 23, 2022 at 20:47
  • This question is similar to: With JSONDecoder in Swift 4, can missing keys use a default value instead of having to be optional properties?. If you believe it’s different, please edit the question, make it clear how it’s different and/or how the answers on that question are not helpful for your problem. Commented Jun 2 at 12:50

1 Answer 1

7

As 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"
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

It sucks that there are no other solutions to this apparently, thank you for taking your time with that!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.