# Dictionarys encoding strategy

**URL:** <https://forums.swift.org/t/dictionarys-encoding-strategy/11973>\
**Category:** Using Swift\
**Created:** [April 18, 2018, 8:23am UTC](https://forums.swift.org/t/dictionarys-encoding-strategy/11973 "2018-04-18T08:23:25Z")\
**Posts on this page:** 1\
**Showing post:** 2

<div class="post-metadata">

**Author:** ![itaiferber](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/itaiferber/32/33840_2.png) [@itaiferber](https://forums.swift.org/u/itaiferber)\
**Post date:** [April 18, 2018, 4:33pm UTC](https://forums.swift.org/t/dictionarys-encoding-strategy/11973/2 "2018-04-18T16:33:43Z")

</div>

There are two answers to your questions here:

> [@cherrywoods](#):
>
> Why just String and Int?

There are corner cases here around integer coding keys which don't always have good answers. The biggest issue to deal with is conversion between integer sizes:

1. It's always safe to promote an integer type smaller than `Int` to an `Int`, so it would be possible to _encode_ those values as `CodingKey`s. On decode, though, you could get a `CodingKey` whose integer value does not fit in, say, an `Int8`. You could consider this to be a type mismatch, potentially, but it's one thing for an integer value to not map to a real `CodingKey`, and another for the integer value to be completely out of bounds. Given the API contract of `CodingKey`s, it's reasonable to assume that they should be able to use the entire range of `Int` values; it's a different matter to expect to decode an `Int8` value from an unkeyed container and get back something that would require an `Int64` or similar
2. A bigger problem is what happens for types like `UInt` — if a dictionary has `UInt` keys which all happen to fit in an `Int`, should it be encoded as a keyed container? And if one of the keys does not fit in an `Int`? There is an inconsistency in formats here based on the actual values of the keys, and not the types themselves

It is considerably simpler to define the behavior here around the `CodingKey`s contract itself: all keys have a `String` value, and potentially an `Int` value. Those types map losslessly into `CodingKey`s; otherwise, we do the safe thing of not making assumptions.

> [@cherrywoods](#):
>
> I think all types conforming to LosslessStringConvertible could be transformed into „lossless, unique” string keys, as it’s documentation states. Or am I getting the LosslessStringConertible protocol wrong?
> 
> \<snip\>
> 
> Is this maybe for compatibility with older versions, where this casts didn‘t work?

The casts would work, certainly, but the question is one of semantics. Just because a type conforms to `LosslessStringConvertible`, does it mean that it's safe/reasonable to convert it into a string key and back?

1. There are types for which the string representation might be significantly larger or more difficult to represent than the underlying `Codable` representation
2. Considering also the interaction with the above types: `Int8` is `LosslessStringConvertible`, which means that in a format that differentiates between `Int` and `String` keys, encoding `[1: "one", 2: "two"]` as `[Int: String]` would encode as `[1: "one", 2: "two"]`, while encoding the same value as `[Int8: String]` would encode it as `["1": "one", "2": "two"]`; the differences here might be non-obvious if you don't know the original types

From a semantic standpoint, though — it's not necessarily clear what the _intent_ is behind annotating a type with `LosslessStringConvertible`; just because a type is indeed convertible doesn't necessarily mean we should prioritize that format over their own `Codable` format.

* * *

None of these are insurmountable differences, by the way; it's possible to come up with semantics that make sense for all of these cases. It is, however, significantly simpler to express that "`String`- and `Int`-keyed dictionaries use `CodingKey`s; everything else uses the unkeyed format".

---

_[View the full topic](https://forums.swift.org/t/dictionarys-encoding-strategy/11973)._
