Yeah, there are quite some limitations here... Note how you had to put decoding Int before decoding Double. Or what if there was a Float in one case's payload and Double in another, or String in one and StringProtocol type in another. The limitations are more serious that just that, e.g, you might have an enum with:
enum E {
case a(A)
case b(B)
...
}
where A and B are similar types as far as decoding is concerned:
// example
struct A { let x: UInt }
struct B { let x: Int }
or a more complicated case:
enum E {
case a([A])
case b([B])
...
}
with the payload to decode being an array of 100K positive elements and the last element being negative.
Ideally type information should be available during decoding one way or another... JSON won't be able preserving that (aside from embedding extra information in some custom way) but other serialisation formats (like XML) will be able preserving it.