Working with JSON Data in Swift
Swift and JSON don’t play nicely together. Swift wants everything to have a type; JSON, on the other hand, is a blob of data from which types can only be inferred.
How can we write good Swift when working with JSON?
JSONValue
The JSONValue
enum is a Swift container around JSON values. It can represent any of the primitive JSON types:
- String
- Number (Double or Integer)
- Boolean
- Null
- Object
- Array
To implement JSONValue
, we’ll create six enum cases, corresponding to the six possible JSON types listed above.
Next up, we’re going to implement decoding. This allows us to transform a blob of JSON data into usable Swift data.
Notice that for Dictionaries and Arrays, the nested type is JSONValue
. This is because the decoder doesn’t know what type the Dictionary or Array contains; and, in fact, they could contain multiple types as JSON doesn’t enforce homogeneity.
Test Cases for JSONValue
can be found at this gist.
JSONPrimitive
JSONPrimitive
is a “pseudo-type” that is adopted by the Swift types which correspond to primitive JSON types.
To handle null
, we extend Optional
to adopt JSONPrimitive
. We also extend JSONValue
itself so it can act as a JSONPrimitive
.
Finally, to extract the wrapped value, we add a property value
to the JSONValue
enum, which returns an Optional JSONPrimitive?
. This return value represents the raw value and can be passed around instead of Any
.