Demystifying Dynamic JSON Parsing in Swift : Mastering Alamofire Integration . part — 1

Sepehr
5 min readJun 16, 2023

--

JSON (JavaScript Object Notation) is a widely used format for data interchange in modern applications. When working with dynamic JSON data in Swift, efficiently parsing and utilizing it can be a challenge. In this article, we will explore how to parse dynamic JSON and create a model for cars using Swift. We will also dive into the MVVM (Model-View-ViewModel) architecture and leverage popular libraries such as Alamofire and Combine to handle networking and data binding. Additionally, we’ll discuss error handling techniques using Combine and demonstrate the usage of dependency injection for the CarView.

source : https://www.gq-magazine.co.uk

Parsing dynamic JSON requires understanding the intricacies of working with varying data structures. We will uncover the key concepts and techniques for parsing dynamic JSON in Swift. By the end, you will have a clear understanding of how to handle dynamic JSON and efficiently extract the necessary data.

This is our JSON

{
"pagination": {
"currentPage": 1,
"perPage": 10,
"totalPages": 1,
"totalCars": 5,
"take": 5
},
"cars": [
{
"id": "1",
"createdAt": "2023-02-14T13:28:38.264Z",
"make": "Toyota",
"model": "Camry",
"year": 2022,
"type": "Mechanical",
"engine": {
"type": "Mechanical",
"cylinders": 4,
"fuelType": "Gasoline",
"displacement": 2.5
}
},
{
"id": "2",
"createdAt": "2023-02-11T13:18:18.264Z",
"make": "Honda",
"model": "Accord",
"year": 2022,
"type": "Mechanical",
"engine": {
"type": "Mechanical",
"cylinders": 4,
"fuelType": "Gasoline",
"displacement": 2.0
}
},
{
"id": "3",
"createdAt": "2023-02-14T10:28:18.264Z",
"make": "Tesla",
"model": "Model 3",
"year": 2022,
"type": "Electrical",
"engine": {
"type": "Electrical",
"power": 283,
"torque": 375,
"battery": {
"capacity": 82,
"technology": "Lithium-ion"
}
}
},
{
"id": "4",
"createdAt": "2022-11-14T13:28:18.264Z",
"make": "Ford",
"model": "Mustang",
"year": 2022,
"type": "Mechanical",
"engine": {
"type": "Mechanical",
"cylinders": 8,
"fuelType": "Gasoline",
"displacement": 5.0
}
},
{
"id": "5",
"createdAt": "2022-12-14T13:28:18.264Z",
"make": "Nissan",
"model": "Leaf",
"year": 2022,
"type": "Electrical",
"engine": {
"type": "Electrical",
"power": 147,
"torque": 236,
"battery": {
"capacity": 40,
"technology": "Lithium-ion"
}
}
}
]
}

Before we delve into parsing the dynamic JSON into a structured Car model, let’s take a closer look at the JSON structure we’ll be working with. Understanding its properties and how they relate to our Swift model is crucial for successful parsing and modeling.

In our JSON representation, you’ll notice that we have various properties such as “make,” “model,” “year,” “color,” “mileage,” and “isElectric.” These properties provide essential information about the car. However, one particular property, “engine,” presents an interesting challenge. Unlike other properties, “engine” doesn’t have a static object. It can be either an “ElectricalEngineDto” or a “MechanicalEngineDto” depending on the car’s specifications.

This dynamic behavior of the “engine” property adds complexity to our JSON parsing process. We need to account for the varying types and handle them accordingly to ensure accurate modeling in our Swift code.

In the upcoming sections, we will explore how to handle this dynamic aspect of the JSON and successfully parse it into our Car model. We’ll demonstrate techniques to handle the different engine types, allowing for flexible and robust parsing in Swift.

Let’s continue with the exciting journey of demystifying dynamic JSON parsing in Swift!

Parsing Dynamic JSON to Cars Model in Swift

Now that we have a clear understanding of our JSON structure, let’s dive into the process of parsing this dynamic JSON into a structured Car model using Swift. To achieve this, we will leverage Swift’s Codable protocol, which provides a convenient way to encode and decode JSON data.

struct Car: Codable {
let id : String
let createdAt: String,
let make: String
let model: String
let year: Int
let type: EngineType
let engine: Engine
}

enum EngineType: String, Codable {
case electrical = "Electrical"
case mechanical = "Mechanical"
}

1. Why We Use Codable and Engine model Extends Codable

Codable is a powerful protocol that combines the functionality of both Encodable and Decodable protocols. By adopting Codable in our Car model, we can easily convert JSON data to Swift objects and vice versa. In addition, we extend the Codable protocol to our Engine type, enabling us to encode and decode the different types of engines present in our JSON.

2. The Role of Decoder and init(from decoder: Decoder)

The Decoder is responsible for decoding the JSON data into our Swift model. We define a special constructor called init(from decoder: Decoder) in our Engine model to handle the dynamic nature of the "engine" property. This constructor allows us to customize the decoding process and make decisions based on the actual type encountered in the JSON.

3. Decoding JSON with Container in the Engine Model

Within the init(from decoder: Decoder) constructor, we utilize a singleValueContainer to decode the JSON data. This container provides access to the underlying single value of the "engine" property. We then attempt to decode the value as an ElectricalEngineDto or a MechanicalEngineDto using conditional statements. Based on the successful decoding, we assign the appropriate engine type to our Engine model. If none of the decoding attempts match, we throw a DecodingError indicating an invalid engine type.

4. Encoding the Engine Model

To support encoding our Engine model back into JSON, we implement the encode(to encoder: Encoder) method. Within this method, we utilize an encoder.singleValueContainer() to obtain a container for the single value of the engine. We then encode either the electricalEngine or mechanicalEngine based on their presence. If none of the engine types are present, we throw an EncodingError indicating an invalid engine value.

By implementing these encoding and decoding strategies, we ensure that our Car model can accurately represent the dynamic JSON data, including the different engine types.

struct Engine: Codable {
let electricalEngine: ElectricalEngineDto?
let mechanicalEngine: MechanicalEngineDto?

init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()

if let electricalEngine = try? container.decode(ElectricalEngineDto.self) {
self.electricalEngine = electricalEngine
self.mechanicalEngine = nil
} else if let mechanicalEngine = try? container.decode(MechanicalEngineDto.self) {
self.electricalEngine = nil
self.mechanicalEngine = mechanicalEngine
} else {
throw DecodingError.typeMismatch(Engine.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Invalid engine type"))
}
}

func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
if let electricalEngine = electricalEngine {
try container.encode(electricalEngine)
} else if let mechanicalEngine = mechanicalEngine {
try container.encode(mechanicalEngine)
} else {
throw EncodingError.invalidValue(
self,
EncodingError.Context(
codingPath: encoder.codingPath,
debugDescription: "Invalid engine value"
)
)
}
}


}
struct MechanicalEngineDto: Codable {
let type: String
let cylinders: Int
let fuelType: String
let displacement: Double
}
struct ElectricalEngineDto: Codable {
let type: String
let power: Int
let torque: Int
let battery: Battery
}

struct Battery: Codable {
let capacity: Int
let technology: String
}

I

Are you ready to take your Swift project to new heights?

The implementation of dynamic JSON parsing and modeling is just the beginning of our journey. I appreciate your enthusiasm and interest in Swift development! Your commitment to learning and exploring new concepts is commendable. By delving into dynamic JSON parsing, MVVM architecture, and utilizing libraries like Alamofire and Combine, you are taking significant steps to become a skilled and versatile developer.

Join me in the next section…

source : https://tenor.com/view/lets-go-gif-22712392

I hope you enjoyed the article. Thanks for reading! 🥳️
you can see cars project at github

--

--

Sepehr

Proficient in Java, Kotlin, Dart, Swift, and cross-platform development, I excel in creating user-centric applications that marry functionality with design