-
Notifications
You must be signed in to change notification settings - Fork 88
JSON Parsing Cheat Sheet
JSON Values | Swift Type |
---|---|
Anything contained in braces, { ... }
|
struct (usually), class, or dictionary |
Anything contained in brackets [ ... ]
|
Array |
Anything contained in quotes " ... "
|
String |
Any whole number, e.g. 10
|
Int |
Anything with a decimal, e.g. 25.2
|
Float or Double
|
A boolean (without quotes), true or false
|
Bool |
We're just storing a simple JSON object using a Swift string.
let json = """
{
"model": "iPhone XS,
"released": 2018
}
""".data(using: .utf8)!
We represent this object in Swift using a struct
struct Phone: Codable {
let model: String
let released: Int
}
And decode it using a JSONDecoder
, passing in Phone.self
as the type to parse into. We should handle parsing errors with do catch
.
do {
let decoder = JSONDecoder()
let phone = try decoder.decode(Phone.self, from: json)
print(phone)
} catch {
print(error)
}
Use a CodingKeys
enum. Here we change released
to releaseYear
. In some JSON objects, it will be necessary to use CodingKeys
if the keys are not valid Swift property names.
struct Phone: Codable {
let model: String
let released: Int
enum CodingKeys: String, CodingKey {
case model
case releaseYear = "released"
}
}
For example, if we added a JSON object to represent the screen resolution.
let json = """
{
"model": "iPhone XS",
"released": 2018,
"screen_resolution": {
"width": 1125,
"height": 2436
}
}
""".data(using: .utf8)!
Create a Codable
struct representing the properties in each level of indenting. Start with the innermost. The resolution...
struct Resolution: Codable {
let width: Int
let height: Int
}
And for the root object, which represents the phone. Notice that a property is added for screenResolutin
, and it's also added to the CodingKeys
enum.
struct Phone: Codable {
let model: String
let releaseYear: Int
let screenResolution: Resolution
enum CodingKeys: String, CodingKey {
case model
case releaseYear = "released"
case screenResolution = "screen_resolution"
}
}
Here, we have multiple JSON objects in an array
let json = """
[
{
"model": "iPhone XS",
"released": 2018,
"screen_resolution": {
"width": 1125,
"height": 2436
}
},
{
"model": "iPhone 8",
"released": 2017,
"screen_resolution": {
"width": 750,
"height": 1920
}
}
]
""".data(using: .utf8)!
Modify the parsing line to be an array of whatever the objects are.
let phone = try decoder.decode([Phone].self, from: json)
Any Codable
type, including the basic types, means that an array of that type is also Codable
!
Some JSON will be structured where the key names won't always be known (common in NoSQL databases like Firebase). For example, these "users" are values for keys, which are their user IDs.
let users = """
{
"25801": {
"display_name": "Owen",
"joined": 2015
},
"39447": {
"display_name": "Jessica",
"joined": 2016
}
}
""".data(using: .utf8)!
The JSON objects stored as values still need a Codable
struct.
struct User: Codable {
let displayName: String
let joined: Int
enum CodingKeys: String, CodingKey {
case displayName = "display_name"
case joined
}
}
But we would parse this into a dictionary with string keys and User
values.
let usersDict = try decoder.decode([String: User].self, from: users)
And use the keys
and values
properties of Swift dictionaries to access the keys and values directly.
usersDict.keys
usersDict.values