Working with JSON in Swift: Parsing and Serialization for Beginners
\n\nJSON (JavaScript Object Notation) is the most popular data exchange format in modern mobile and web applications. If you are developing for iOS or macOS in Swift, the ability to parse and serialize JSON is a mandatory skill. In this article, we will cover all the main ways to work with JSON: from the classic JSONSerialization to the modern Codable protocol. The material is aimed at beginner developers who are already familiar with the basics of Swift.
What is JSON and why is it needed in Swift?
\n\nJSON is a text format based on JavaScript syntax. It consists of key-value pairs, nested objects, and arrays. In iOS development, JSON is used for:
\n\n- \n
- Retrieving data from REST API servers \n
- Saving application configurations and settings \n
- Exchanging data between application modules \n
- Working with databases (e.g., Firebase or CoreData + JSON) \n
In Swift, there are two main approaches to working with JSON: the old way using JSONSerialization (from Foundation) and the modern way using the Codable, Encodable, and Decodable protocols. We will start with the simpler JSONSerialization to understand the mechanics, and then move on to the powerful Codable.
Parsing JSON with JSONSerialization (Foundation)
\n\nJSONSerialization is a built-in Foundation class that converts JSON data into Swift objects (dictionaries and arrays). This method has existed since the early versions of Swift and is still used in legacy projects. Let's look at an example.
Suppose we have a JSON string with user information:
\n\nlet jsonString = """\n{\n "name": "Ivan",\n "age": 30,\n "email": "ivan@example.com",\n "isActive": true,\n "hobbies": ["reading", "programming", "sports"]\n}\n"""\n\nTo parse this JSON, we first convert the string to Data, and then use JSONSerialization:
import Foundation\n\nif let jsonData = jsonString.data(using: .utf8) {\n do {\n if let dictionary = try JSONSerialization.jsonObject(with: jsonData, options: []) as? [String: Any] {\n print("Name: \\(dictionary["name"] ?? "No data")")\n print("Age: \\(dictionary["age"] ?? "No data")")\n if let hobbies = dictionary["hobbies"] as? [String] {\n print("Hobbies: \\(hobbies.joined(separator: ", "))")\n }\n }\n } catch {\n print("JSON parsing error: \\(error.localizedDescription)")\n }\n}\n\nImportant points:
\n- \n
- Always use
try-catch— parsing can throw an error. \n - The result comes as
Any, so you need to cast it to a specific type ([String: Any]for an object,[Any]for an array). \n - The options
.mutableContainersand.fragmentsAllowedallow you to control parsing flexibility. \n
Modern approach: the Codable protocol
\n\nStarting with Swift 4, Apple introduced the Codable protocol (combining Encodable and Decodable). This is real "magic" — you just declare a structure, and Swift knows how to parse and serialize data on its own. Let's rewrite the previous example using Codable.
1. Declaring the data model
\n\nstruct User: Codable {\n let name: String\n let age: Int\n let email: String\n let isActive: Bool\n let hobbies: [String]\n}\n\nNote: the field names in the structure must match the JSON keys (case-sensitive). If the keys differ (e.g., snake_case), use CodingKeys.