How to define "unfrozen" enums?

Currently I have a JSON payload with a property mapped to an enum with associated values and custom decoding.

If it weren't for the associated values, I could declare my enum with rawType of String, and this will give me the option to handle "default" cases (not defined cases):

enum Foo: String {
  case foo
}

switch foo {
case .foo:
  // do something
default:
  // handle default case
}

However, because of the associated values, the enum cannot have a rawType of String, and I don't get the benefit of having a "default" case.

enum Bar {
  case bar(value: Any)
}

switch bar {
case .bar:
  // do something
default:  // <------------------------ Not possible :(
  // handle default case
}

When decoding JSON, this means the decoding operation will throw an exception if the property contained an unsupported value.

While I can catch and respond to this exception, I'd like to know if there is a way to provide that "default" case. Something like having custom "unfrozen" enums.

Is this possible? Thanks!

I usually just have an unknown case that the custom Decodable implementation falls into when certain errors occur. It really depends on what you're using the value for and if there's a good unknown behavior.

Adding another case to the enum sounds like a good idea, will try, thanks!

This is false. Consider this example. Size has a rawValue of type String.

enum Size: RawRepresentable {
    
    case small
    case medium
    case large
    case other(String)
    
    init?(rawValue: String) {
        switch rawValue {
            case "small":
                self = .small
            case "medium":
                self = .medium
            case "large":
                self = .large
            default:
                self = .other(rawValue)
        }
    }

    var rawValue: String {
        switch self {
            case .small:
                return "small"
            case .medium:
                return "medium"
            case .large:
                return "large"
            case .other(let size):
                return size
        }
    }

}
Terms of Service

Privacy Policy

Cookie Policy