How do I declare an all-encompassing Codable Dictionary?

A Dictionary that can accept anything can be declared as [AnyHashable: Any]. But what if it needs to be Codable too? Would [AnyHashable & Codable: Codable] work?

[AnyHashable & Codable : Codable] expresses the requirement that these types be Codable, but note that this is not terribly useful as existential Codable values cannot be encoded or decoded. In order to decode a value, you need to have the concrete type you want — decoding needs to call init(from:) on a type, and calling (AnyHashable & Codable).init(from:) isn’t possible since which concrete type would that give you?

It is possible to express an existential AnyEncodable type, but without knowing your use case better, I wouldn’t recommend doing so unless you really need it, since you run the risk of encoding values you later cannot decode (caveat to this approach).

What are you looking to do here specifically?

2 Likes

Send over JSON data. The data can be of Apple’s usual types: string, integer, floating, Boolean, and arrays, sets, and dictionaries of such.

Generic JSON data can also be typed strongly:

public enum JSON {
    case string(String)
    case number(Float)
    case object([String:JSON])
    case array([JSON])
    case bool(Bool)
    case null
}

Then you can easily convert from Codable to this. Sample code here. (But now that I think about it I don’t know if this helps your case at all.)

1 Like

@zoul's answer is the appropriate one — the right way to represent this is by expressing the type not as an existential, but as a concrete union of types (i.e. "string or integer or floating or boolean or array or set or dictionary or..."); the way this is done in Swift is by declaring an enum with associated values for the different cases that you have.

@zoul links to his JSON code to do this — I have a similar (if more simplified and naïve) version here.

1 Like