macOS Data Serialization Swift Samples

macOS Swift data serialization examples including JSON serialization, deserialization, and XML parsing

Key Facts

Category
Swift
Items
3
Format Families
json, xml

Sample Overview

macOS Swift data serialization examples including JSON serialization, deserialization, and XML parsing This sample set belongs to Swift and can be used to test related workflows inside Elysia Tools.

💻 JSON Serialization swift

🟢 simple ⭐⭐

Serialize Swift objects to JSON using Codable and JSONSerialization

⏱️ 25 min 🏷️ swift, macos, serialization, json
Prerequisites: Basic Swift knowledge, Codable protocol
// macOS Swift JSON Serialization Examples
// Using Foundation framework

import Foundation

// 1. Basic JSON Serialization with Codable
struct User: Codable {
    let id: Int
    let username: String
    let email: String
    let age: Int
    let isActive: Bool
}

class BasicJSONSerialization {

    static func serializeUser() {
        print("\n--- Basic JSON Serialization ---")

        let user = User(
            id: 1,
            username: "john_doe",
            email: "[email protected]",
            age: 30,
            isActive: true
        )

        // Serialize to JSON
        do {
            let jsonData = try JSONEncoder().encode(user)

            if let jsonString = String(data: jsonData, encoding: .utf8) {
                print("Serialized JSON:")
                print(jsonString)
            }

            // Also print as pretty JSON
            let json = try JSONSerialization.jsonObject(with: jsonData)
            let prettyData = try JSONSerialization.data(withJSONObject: json, options: .prettyPrinted)
            if let prettyString = String(data: prettyData, encoding: .utf8) {
                print("\nPretty printed:")
                print(prettyString)
            }

        } catch {
            print("Error serializing: \(error)")
        }
    }
}

// 2. JSON Serialization with Options
class JSONSerializationWithOptions {

    static func serializeWithOptions() {
        print("\n--- JSON Serialization with Options ---")

        let user = User(id: 1, username: "jane", email: "[email protected]", age: 25, isActive: false)

        // Custom encoder
        let encoder = JSONEncoder()

        // Pretty print
        encoder.outputFormatting = .prettyPrinted

        // Sorted keys
        encoder.outputFormatting.insert(.sortedKeys)

        // Without escaping slashes
        encoder.outputFormatting.insert(.withoutEscapingSlashes)

        do {
            let jsonData = try encoder.encode(user)
            if let jsonString = String(data: jsonData, encoding: .utf8) {
                print("JSON with options:")
                print(jsonString)
            }

        } catch {
            print("Error: \(error)")
        }

        // Minimal encoding
        encoder.outputFormatting = []
        do {
            let jsonData = try encoder.encode(user)
            if let jsonString = String(data: jsonData, encoding: .utf8) {
                print("\nMinimal JSON (no whitespace):")
                print(jsonString)
            }
        } catch {
            print("Error: \(error)")
        }
    }
}

// 3. Serialize Array of Objects
class SerializeArray {

    static func serializeArray() {
        print("\n--- Serialize Array of Objects ---")

        let users = [
            User(id: 1, username: "john", email: "[email protected]", age: 30, isActive: true),
            User(id: 2, username: "jane", email: "[email protected]", age: 25, isActive: true),
            User(id: 3, username: "bob", email: "[email protected]", age: 35, isActive: false)
        ]

        do {
            let encoder = JSONEncoder()
            encoder.outputFormatting = .prettyPrinted

            let jsonData = try encoder.encode(users)

            if let jsonString = String(data: jsonData, encoding: .utf8) {
                print("Serialized array:")
                print(jsonString)
            }

            // Get array size
            print("\nArray size: \(users.count) users")
            print("JSON size: \(jsonData.count) bytes")

        } catch {
            print("Error: \(error)")
        }
    }
}

// 4. Serialize Dictionary
class SerializeDictionary {

    static func serializeDictionary() {
        print("\n--- Serialize Dictionary ---")

        let userDict: [String: Any] = [
            "id": 1,
            "username": "john_doe",
            "email": "[email protected]",
            "age": 30,
            "isActive": true,
            "tags": ["admin", "user"],
            "metadata": [
                "created": "2024-01-15",
                "updated": "2024-01-20"
            ] as [String: Any]
        ]

        do {
            let jsonData = try JSONSerialization.data(withJSONObject: userDict, options: .prettyPrinted)

            if let jsonString = String(data: jsonData, encoding: .utf8) {
                print("Serialized dictionary:")
                print(jsonString)
            }

        } catch {
            print("Error: \(error)")
        }
    }
}

// 5. Custom Key Encoding
struct Employee: Codable {
    let firstName: String
    let lastName: String
    let employeeId: Int

    enum CodingKeys: String, CodingKey {
        case firstName = "first_name"
        case lastName = "last_name"
        case employeeId = "employee_id"
    }
}

class CustomKeyEncoding {

    static func serializeWithCustomKeys() {
        print("\n--- Custom Key Encoding ---")

        let employee = Employee(
            firstName: "John",
            lastName: "Doe",
            employeeId: 12345
        )

        do {
            let encoder = JSONEncoder()
            encoder.outputFormatting = .prettyPrinted

            let jsonData = try encoder.encode(employee)

            if let jsonString = String(data: jsonData, encoding: .utf8) {
                print("Serialized with custom keys:")
                print(jsonString)
            }

        } catch {
            print("Error: \(error)")
        }
    }
}

// 6. Serialize with Date Encoding
struct Event: Codable {
    let name: String
    let date: Date
    let attendees: Int
}

class DateEncoding {

    static func serializeWithDate() {
        print("\n--- Serialize with Date Encoding ---")

        let event = Event(
            name: "Conference",
            date: Date(),
            attendees: 150
        )

        do {
            let encoder = JSONEncoder()
            encoder.outputFormatting = .prettyPrinted

            // Default date encoding (seconds since 1970)
            encoder.dateEncodingStrategy = .deferredToDate

            let jsonData = try encoder.encode(event)

            if let jsonString = String(data: jsonData, encoding: .utf8) {
                print("Default date encoding:")
                print(jsonString)
            }

            // ISO 8601 date encoding
            encoder.dateEncodingStrategy = .iso8601

            let isoData = try encoder.encode(event)

            if let isoString = String(data: isoData, encoding: .utf8) {
                print("\nISO 8601 date encoding:")
                print(isoString)
            }

            // Custom date formatting
            let formatter = DateFormatter()
            formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
            encoder.dateEncodingStrategy = .formatted(formatter)

            let customData = try encoder.encode(event)

            if let customString = String(data: customData, encoding: .utf8) {
                print("\nCustom date format:")
                print(customString)
            }

        } catch {
            print("Error: \(error)")
        }
    }
}

// 7. Serialize Nested Objects
struct Address: Codable {
    let street: String
    let city: String
    let state: String
    let zipCode: String
}

struct Person: Codable {
    let name: String
    let age: Int
    let address: Address
    let phoneNumbers: [String]
}

class NestedSerialization {

    static func serializeNested() {
        print("\n--- Serialize Nested Objects ---")

        let person = Person(
            name: "John Doe",
            age: 30,
            address: Address(
                street: "123 Main St",
                city: "New York",
                state: "NY",
                zipCode: "10001"
            ),
            phoneNumbers: ["555-1234", "555-5678"]
        )

        do {
            let encoder = JSONEncoder()
            encoder.outputFormatting = .prettyPrinted

            let jsonData = try encoder.encode(person)

            if let jsonString = String(data: jsonData, encoding: .utf8) {
                print("Serialized nested object:")
                print(jsonString)
            }

        } catch {
            print("Error: \(error)")
        }
    }
}

// 8. Conditional Encoding
struct Product: Codable {
    let id: Int
    let name: String
    let price: Double
    let discountPrice: Double?

    // Encode only if there's a discount
    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)

        try container.encode(id, forKey: .id)
        try container.encode(name, forKey: .name)
        try container.encode(price, forKey: .price)

        if let discount = discountPrice {
            try container.encode(discount, forKey: .discountPrice)
        }
    }

    enum CodingKeys: String, CodingKey {
        case id, name, price, discountPrice
    }
}

class ConditionalEncoding {

    static func demonstrateConditionalEncoding() {
        print("\n--- Conditional Encoding ---")

        let productWithDiscount = Product(id: 1, name: "Widget", price: 99.99, discountPrice: 79.99)
        let productWithoutDiscount = Product(id: 2, name: "Gadget", price: 49.99, discountPrice: nil)

        let encoder = JSONEncoder()
        encoder.outputFormatting = .prettyPrinted

        do {
            let data1 = try encoder.encode(productWithDiscount)
            let data2 = try encoder.encode(productWithoutDiscount)

            print("Product with discount:")
            if let json1 = String(data: data1, encoding: .utf8) {
                print(json1)
            }

            print("\nProduct without discount:")
            if let json2 = String(data: data2, encoding: .utf8) {
                print(json2)
            }

        } catch {
            print("Error: \(error)")
        }
    }
}

// 9. Serialize to File
class SerializeToFile {

    static func serializeToFile() {
        print("\n--- Serialize to File ---")

        let user = User(id: 1, username: "john_doe", email: "[email protected]", age: 30, isActive: true)

        let filePath = "/tmp/user.json"

        do {
            let encoder = JSONEncoder()
            encoder.outputFormatting = .prettyPrinted

            let jsonData = try encoder.encode(user)

            // Write to file
            try jsonData.write(to: URL(fileURLWithPath: filePath))

            print("JSON written to file: \(filePath)")

            // Read file size
            let attributes = try FileManager.default.attributesOfItem(atPath: filePath)
            if let fileSize = attributes[.size] as? UInt64 {
                print("File size: \(fileSize) bytes")
            }

            // Read and verify
            let readData = try Data(contentsOf: URL(fileURLWithPath: filePath))
            if let jsonString = String(data: readData, encoding: .utf8) {
                print("\nFile contents:")
                print(jsonString)
            }

        } catch {
            print("Error: \(error)")
        }
    }
}

// 10. Streaming JSON Serialization
class StreamingSerialization {

    static func streamArrayToJSON() {
        print("\n--- Streaming JSON Serialization ---")

        // Create large array
        let users = (1...100).map { i in
            User(id: i, username: "user\(i)", email: "user\(i)@test.com", age: 20 + i % 50, isActive: i % 2 == 0)
        }

        print("Streaming \(users.count) users to JSON...")

        do {
            let encoder = JSONEncoder()

            // Encode to data
            let startTime = Date()
            let jsonData = try encoder.encode(users)
            let elapsed = Date().timeIntervalSince(startTime)

            print("Encoded \(jsonData.count) bytes in \(elapsed) seconds")

            // Show first 500 characters
            if let jsonString = String(data: jsonData, encoding: .utf8) {
                print("\nFirst 500 characters:")
                print(String(jsonString.prefix(500)))
            }

        } catch {
            print("Error: \(error)")
        }
    }

    static func writeStreamToFile(_ items: [User], filePath: String) {
        print("\n--- Write Stream to File ---")

        do {
            let encoder = JSONEncoder()
            encoder.outputFormatting = .prettyPrinted

            let jsonData = try encoder.encode(items)
            try jsonData.write(to: URL(fileURLWithPath: filePath))

            print("Wrote \(items.count) items to \(filePath)")

            let attributes = try FileManager.default.attributesOfItem(atPath: filePath)
            if let fileSize = attributes[.size] as? UInt64 {
                print("File size: \(fileSize) bytes")
            }

        } catch {
            print("Error: \(error)")
        }
    }
}

// Main demonstration
func demonstrateJSONSerialization() {
    print("=== macOS Swift JSON Serialization Examples ===")

    BasicJSONSerialization.serializeUser()
    JSONSerializationWithOptions.serializeWithOptions()
    SerializeArray.serializeArray()
    SerializeDictionary.serializeDictionary()
    CustomKeyEncoding.serializeWithCustomKeys()
    DateEncoding.serializeWithDate()
    NestedSerialization.serializeNested()
    ConditionalEncoding.demonstrateConditionalEncoding()
    SerializeToFile.serializeToFile()
    StreamingSerialization.streamArrayToJSON()

    let users = (1...50).map { i in
        User(id: i, username: "stream\(i)", email: "stream\(i)@test.com", age: 20 + i, isActive: true)
    }
    StreamingSerialization.writeStreamToFile(users, filePath: "/tmp/users_stream.json")

    print("\n=== All JSON Serialization Examples Completed ===")
}

// Run demonstration
demonstrateJSONSerialization()

💻 JSON Deserialization swift

🟡 intermediate ⭐⭐⭐

Deserialize JSON data into Swift objects using Codable and JSONDecoder

⏱️ 30 min 🏷️ swift, macos, serialization, json
Prerequisites: Intermediate Swift, Codable protocol, Error handling
// macOS Swift JSON Deserialization Examples
// Using Foundation framework

import Foundation

// 1. Basic JSON Deserialization
struct User: Codable {
    let id: Int
    let username: String
    let email: String
    let age: Int
    let isActive: Bool
}

class BasicJSONDeserialization {

    static func deserializeUser() {
        print("\n--- Basic JSON Deserialization ---")

        let jsonString = """
        {
            "id": 1,
            "username": "john_doe",
            "email": "[email protected]",
            "age": 30,
            "isActive": true
        }
        """

        if let jsonData = jsonString.data(using: .utf8) {
            do {
                let user = try JSONDecoder().decode(User.self, from: jsonData)

                print("Decoded user:")
                print("  ID: \(user.id)")
                print("  Username: \(user.username)")
                print("  Email: \(user.email)")
                print("  Age: \(user.age)")
                print("  Active: \(user.isActive)")

            } catch {
                print("Error decoding: \(error)")
            }
        }
    }
}

// 2. Deserialize Array
class DeserializeArray {

    static func deserializeArray() {
        print("\n--- Deserialize Array ---")

        let jsonArray = """
        [
            {
                "id": 1,
                "username": "john",
                "email": "[email protected]",
                "age": 30,
                "isActive": true
            },
            {
                "id": 2,
                "username": "jane",
                "email": "[email protected]",
                "age": 25,
                "isActive": true
            },
            {
                "id": 3,
                "username": "bob",
                "email": "[email protected]",
                "age": 35,
                "isActive": false
            }
        ]
        """

        if let jsonData = jsonArray.data(using: .utf8) {
            do {
                let users = try JSONDecoder().decode([User].self, from: jsonData)

                print("Decoded \(users.count) users:")
                for user in users {
                    print("  \(user.username) - \(user.email)")
                }

            } catch {
                print("Error decoding: \(error)")
            }
        }
    }
}

// 3. Deserialize from File
class DeserializeFromFile {

    static func deserializeFromFile() {
        print("\n--- Deserialize from File ---")

        // First, create a file
        let filePath = "/tmp/users_read.json"
        let users = [
            User(id: 1, username: "alice", email: "[email protected]", age: 28, isActive: true),
            User(id: 2, username: "bob", email: "[email protected]", age: 32, isActive: false)
        ]

        // Write to file first
        if let jsonData = try? JSONEncoder().encode(users) {
            try? jsonData.write(to: URL(fileURLWithPath: filePath))
            print("Created test file: \(filePath)")
        }

        // Now read from file
        if let jsonData = try? Data(contentsOf: URL(fileURLWithPath: filePath)) {
            do {
                let decoder = JSONDecoder()
                let decodedUsers = try decoder.decode([User].self, from: jsonData)

                print("\nDecoded from file:")
                for user in decodedUsers {
                    print("  \(user.username) (\(user.age))")
                }

            } catch {
                print("Error: \(error)")
            }
        }
    }
}

// 4. Custom Key Decoding
struct Employee: Codable {
    let firstName: String
    let lastName: String
    let employeeId: Int

    enum CodingKeys: String, CodingKey {
        case firstName = "first_name"
        case lastName = "last_name"
        case employeeId = "employee_id"
    }
}

class CustomKeyDecoding {

    static func deserializeWithCustomKeys() {
        print("\n--- Custom Key Decoding ---")

        let jsonString = """
        {
            "first_name": "John",
            "last_name": "Doe",
            "employee_id": 12345
        }
        """

        if let jsonData = jsonString.data(using: .utf8) {
            do {
                let employee = try JSONDecoder().decode(Employee.self, from: jsonData)

                print("Decoded employee:")
                print("  First Name: \(employee.firstName)")
                print("  Last Name: \(employee.lastName)")
                print("  Employee ID: \(employee.employeeId)")

            } catch {
                print("Error: \(error)")
            }
        }
    }
}

// 5. Date Decoding
struct Event: Codable {
    let name: String
    let date: Date
    let attendees: Int
}

class DateDecoding {

    static func deserializeWithDate() {
        print("\n--- Date Decoding ---")

        // Default Unix timestamp
        let unixJson = """
        {
            "name": "Conference",
            "date": 1705330800,
            "attendees": 150
        }
        """

        print("Decoding Unix timestamp:")
        if let jsonData = unixJson.data(using: .utf8) {
            do {
                let decoder = JSONDecoder()
                decoder.dateDecodingStrategy = .deferredToDate

                let event = try decoder.decode(Event.self, from: jsonData)

                let formatter = DateFormatter()
                formatter.dateStyle = .medium
                formatter.timeStyle = .short

                print("  Event: \(event.name)")
                print("  Date: \(formatter.string(from: event.date))")
                print("  Attendees: \(event.attendees)")

            } catch {
                print("Error: \(error)")
            }
        }

        // ISO 8601 format
        let isoJson = """
        {
            "name": "Meeting",
            "date": "2024-01-15T10:30:00Z",
            "attendees": 10
        }
        """

        print("\nDecoding ISO 8601:")
        if let jsonData = isoJson.data(using: .utf8) {
            do {
                let decoder = JSONDecoder()
                decoder.dateDecodingStrategy = .iso8601

                let event = try decoder.decode(Event.self, from: jsonData)

                let formatter = DateFormatter()
                formatter.dateStyle = .medium
                formatter.timeStyle = .short

                print("  Event: \(event.name)")
                print("  Date: \(formatter.string(from: event.date))")

            } catch {
                print("Error: \(error)")
            }
        }

        // Custom date format
        let customJson = """
        {
            "name": "Party",
            "date": "2024-01-15 22:00:00",
            "attendees": 50
        }
        """

        print("\nDecoding custom date format:")
        if let jsonData = customJson.data(using: .utf8) {
            do {
                let decoder = JSONDecoder()

                let formatter = DateFormatter()
                formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
                decoder.dateDecodingStrategy = .formatted(formatter)

                let event = try decoder.decode(Event.self, from: jsonData)

                print("  Event: \(event.name)")
                print("  Date: \(event.date)")

            } catch {
                print("Error: \(error)")
            }
        }
    }
}

// 6. Nested Object Decoding
struct Address: Codable {
    let street: String
    let city: String
    let state: String
    let zipCode: String
}

struct Person: Codable {
    let name: String
    let age: Int
    let address: Address
    let phoneNumbers: [String]
}

class NestedDecoding {

    static func deserializeNested() {
        print("\n--- Nested Object Decoding ---")

        let jsonString = """
        {
            "name": "John Doe",
            "age": 30,
            "address": {
                "street": "123 Main St",
                "city": "New York",
                "state": "NY",
                "zipCode": "10001"
            },
            "phoneNumbers": ["555-1234", "555-5678"]
        }
        """

        if let jsonData = jsonString.data(using: .utf8) {
            do {
                let person = try JSONDecoder().decode(Person.self, from: jsonData)

                print("Decoded person:")
                print("  Name: \(person.name)")
                print("  Age: \(person.age)")
                print("  Address:")
                print("    Street: \(person.address.street)")
                print("    City: \(person.address.city)")
                print("    State: \(person.address.state)")
                print("    ZIP: \(person.address.zipCode)")
                print("  Phone numbers: \(person.phoneNumbers.joined(separator: ", "))")

            } catch {
                print("Error: \(error)")
            }
        }
    }
}

// 7. Handling Missing Fields
struct OptionalUser: Codable {
    let id: Int
    let username: String
    let email: String?
    let age: Int?
    let bio: String?
}

class OptionalFieldsDecoding {

    static func deserializeOptionalFields() {
        print("\n--- Handling Missing/Optional Fields ---")

        let jsonString = """
        {
            "id": 1,
            "username": "john_doe"
        }
        """

        if let jsonData = jsonString.data(using: .utf8) {
            do {
                let user = try JSONDecoder().decode(OptionalUser.self, from: jsonData)

                print("Decoded user with optional fields:")
                print("  ID: \(user.id)")
                print("  Username: \(user.username)")
                print("  Email: \(user.email ?? "Not provided")")
                print("  Age: \(user.age?.description ?? "Not provided")")
                print("  Bio: \(user.bio ?? "Not provided")")

            } catch {
                print("Error: \(error)")
            }
        }
    }
}

// 8. Error Handling
class ErrorHandling {

    static func handleDecodingErrors() {
        print("\n--- Decoding Error Handling ---")

        // Invalid JSON
        let invalidJson = "{ invalid json }"

        print("1. Invalid JSON:")
        if let jsonData = invalidJson.data(using: .utf8) {
            do {
                _ = try JSONDecoder().decode(User.self, from: jsonData)
            } catch let DecodingError.dataCorrupted(context) {
                print("  Data corrupted: \(context)")
            } catch let DecodingError.keyNotFound(key, context) {
                print("  Key not found: \(key) - \(context)")
            } catch let DecodingError.typeMismatch(type, context) {
                print("  Type mismatch: \(type) - \(context)")
            } catch let DecodingError.valueNotFound(type, context) {
                print("  Value not found: \(type) - \(context)")
            } catch {
                print("  Other error: \(error)")
            }
        }

        // Missing required field
        let incompleteJson = """
        {
            "id": 1,
            "username": "john"
        }
        """

        print("\n2. Missing required field:")
        if let jsonData = incompleteJson.data(using: .utf8) {
            do {
                _ = try JSONDecoder().decode(User.self, from: jsonData)
            } catch {
                print("  Error: \(error.localizedDescription)")
            }
        }

        // Wrong type
        let wrongTypeJson = """
        {
            "id": "not_a_number",
            "username": "john",
            "email": "[email protected]",
            "age": 30,
            "isActive": true
        }
        """

        print("\n3. Wrong type:")
        if let jsonData = wrongTypeJson.data(using: .utf8) {
            do {
                _ = try JSONDecoder().decode(User.self, from: jsonData)
            } catch {
                print("  Error: \(error.localizedDescription)")
            }
        }
    }
}

// 9. Partial Decoding
class PartialDecoding {

    static func partialDecode() {
        print("\n--- Partial Decoding ---")

        let jsonString = """
        {
            "id": 1,
            "username": "john_doe",
            "email": "[email protected]",
            "age": 30,
            "isActive": true,
            "metadata": {
                "created": "2024-01-15",
                "updated": "2024-01-20"
            },
            "settings": {
                "theme": "dark",
                "notifications": true
            }
        }
        """

        if let jsonData = jsonString.data(using: .utf8) {
            do {
                // Decode only the User part
                let user = try JSONDecoder().decode(User.self, from: jsonData)

                print("Partially decoded user:")
                print("  Username: \(user.username)")
                print("  Email: \(user.email)")

                // Decode entire JSON to dictionary
                if let json = try JSONSerialization.jsonObject(with: jsonData) as? [String: Any] {
                    print("\nFull JSON available for other fields:")
                    if let metadata = json["metadata"] as? [String: String] {
                        print("  Created: \(metadata["created"] ?? "")")
                        print("  Updated: \(metadata["updated"] ?? "")")
                    }
                }

            } catch {
                print("Error: \(error)")
            }
        }
    }
}

// 10. Streaming JSON Parsing
class StreamingParsing {

    static func streamJSONArray() {
        print("\n--- Streaming JSON Parsing ---")

        // Simulate large JSON array
        let largeArray = (1...1000).map { i in
            [
                "id": i,
                "username": "user\(i)",
                "email": "user\(i)@test.com",
                "age": 20 + i % 50,
                "isActive": i % 2 == 0
            ] as [String: Any]
        }

        guard let jsonData = try? JSONSerialization.data(withJSONObject: largeArray) else {
            return
        }

        print("Parsing \(jsonData.count) bytes of JSON...")

        let startTime = Date()

        do {
            let users = try JSONDecoder().decode([User].self, from: jsonData)

            let elapsed = Date().timeIntervalSince(startTime)

            print("Parsed \(users.count) users in \(elapsed) seconds")
            print("First user: \(users.first?.username ?? "")")
            print("Last user: \(users.last?.username ?? "")")

        } catch {
            print("Error: \(error)")
        }
    }

    static func parseChunkedJSON() {
        print("\n--- Parse Chunked JSON ---")

        let jsonString = """
        {"users": [
            {"id": 1, "username": "john", "email": "[email protected]", "age": 30, "isActive": true},
            {"id": 2, "username": "jane", "email": "[email protected]", "age": 25, "isActive": true},
            {"id": 3, "username": "bob", "email": "[email protected]", "age": 35, "isActive": false}
        ]}
        """

        if let jsonData = jsonString.data(using: .utf8) {
            do {
                let decoder = JSONDecoder()

                // Parse as dictionary first
                if let json = try JSONSerialization.jsonObject(with: jsonData) as? [String: Any],
                   let usersArray = json["users"] as? [[String: Any]] {

                    print("Parsed \(usersArray.count) users")

                    // Then decode each user
                    for userDict in usersArray {
                        if let userData = try? JSONSerialization.data(withJSONObject: userDict),
                           let user = try? decoder.decode(User.self, from: userData) {
                            print("  \(user.username)")
                        }
                    }
                }

            } catch {
                print("Error: \(error)")
            }
        }
    }
}

// 11. Dynamic Decoding
class DynamicDecoding {

    static func decodeDynamicJSON() {
        print("\n--- Dynamic JSON Decoding ---")

        let jsonString = """
        {
            "type": "user",
            "data": {
                "id": 1,
                "username": "john_doe",
                "email": "[email protected]",
                "age": 30,
                "isActive": true
            }
        }
        """

        if let jsonData = jsonString.data(using: .utf8) {
            do {
                if let json = try JSONSerialization.jsonObject(with: jsonData) as? [String: Any],
                   let type = json["type"] as? String,
                   let data = json["data"] as? [String: Any] {

                    print("Type: \(type)")

                    // Decode based on type
                    if type == "user" {
                        let userData = try JSONSerialization.data(withJSONObject: data)
                        let user = try JSONDecoder().decode(User.self, from: userData)

                        print("User: \(user.username)")
                    }
                }

            } catch {
                print("Error: \(error)")
            }
        }
    }
}

// Main demonstration
func demonstrateJSONDeserialization() {
    print("=== macOS Swift JSON Deserialization Examples ===")

    BasicJSONDeserialization.deserializeUser()
    DeserializeArray.deserializeArray()
    DeserializeFromFile.deserializeFromFile()
    CustomKeyDecoding.deserializeWithCustomKeys()
    DateDecoding.deserializeWithDate()
    NestedDecoding.deserializeNested()
    OptionalFieldsDecoding.deserializeOptionalFields()
    ErrorHandling.handleDecodingErrors()
    PartialDecoding.partialDecode()
    StreamingParsing.streamJSONArray()
    StreamingParsing.parseChunkedJSON()
    DynamicDecoding.decodeDynamicJSON()

    print("\n=== All JSON Deserialization Examples Completed ===")
}

// Run demonstration
demonstrateJSONDeserialization()

💻 XML Parsing swift

🟡 intermediate ⭐⭐⭐

Parse XML documents using XMLParser and convert to Swift objects

⏱️ 35 min 🏷️ swift, macos, serialization, xml
Prerequisites: Intermediate Swift, XMLParser, Delegate pattern
// macOS Swift XML Parsing Examples
// Using Foundation framework

import Foundation

// 1. Basic XML Parsing
class BasicXMLParser: NSObject, XMLParserDelegate {
    var currentElement: String = ""
    var foundCharacters: String = ""

    func parseXML(xmlString: String) {
        print("\n--- Basic XML Parsing ---")

        guard let data = xmlString.data(using: .utf8) else {
            print("Invalid XML string")
            return
        }

        let parser = XMLParser(data: data)
        parser.delegate = self

        print("Parsing XML:")
        if parser.parse() {
            print("XML parsed successfully")
        } else {
            print("XML parsing failed: \(parser.parserError?.localizedDescription ?? "")")
        }
    }

    // Delegate methods
    func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String: String] = [:]) {
        currentElement = elementName
        foundCharacters = ""

        print("Started element: \(elementName)")

        if !attributeDict.isEmpty {
            print("  Attributes: \(attributeDict)")
        }
    }

    func parser(_ parser: XMLParser, foundCharacters string: String) {
        foundCharacters += string
    }

    func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
        let trimmed = foundCharacters.trimmingCharacters(in: .whitespacesAndNewlines)

        if !trimmed.isEmpty {
            print("  \(elementName): \(trimmed)")
        }

        currentElement = ""
    }

    func parser(_ parser: XMLParser, parseErrorOccurred parseError: Error) {
        print("Parse error: \(parseError)")
    }
}

// 2. Parse XML to Object
struct Book {
    let title: String
    let author: String
    let year: String
    let price: Double
}

class BookParser: NSObject, XMLParserDelegate {
    var books: [Book] = []
    var currentElement: String = ""
    var currentTitle: String = ""
    var currentAuthor: String = ""
    var currentYear: String = ""
    var currentPrice: String = ""

    func parseBooks(xmlString: String) -> [Book] {
        print("\n--- Parse XML to Objects ---")

        guard let data = xmlString.data(using: .utf8) else {
            return []
        }

        let parser = XMLParser(data: data)
        parser.delegate = self

        parser.parse()

        print("Parsed \(books.count) books")

        return books
    }

    func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String: String] = [:]) {
        currentElement = elementName
    }

    func parser(_ parser: XMLParser, foundCharacters string: String) {
        let trimmed = string.trimmingCharacters(in: .whitespacesAndNewlines)
        if !trimmed.isEmpty {
            switch currentElement {
            case "title":
                currentTitle = trimmed
            case "author":
                currentAuthor = trimmed
            case "year":
                currentYear = trimmed
            case "price":
                currentPrice = trimmed
            default:
                break
            }
        }
    }

    func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
        if elementName == "book" {
            let price = Double(currentPrice) ?? 0.0
            let book = Book(title: currentTitle, author: currentAuthor, year: currentYear, price: price)
            books.append(book)

            print("  Book: \(book.title) by \(book.author) - $\(book.price)")

            // Reset
            currentTitle = ""
            currentAuthor = ""
            currentYear = ""
            currentPrice = ""
        }
    }
}

// 3. Parse XML with Attributes
struct Product {
    let id: String
    let category: String
    let name: String
    let price: Double
}

class ProductParser: NSObject, XMLParserDelegate {
    var products: [Product] = []
    var currentElement: String = ""
    var currentId: String = ""
    var currentCategory: String = ""
    var currentName: String = ""
    var currentPrice: String = ""

    func parseProducts(xmlString: String) -> [Product] {
        print("\n--- Parse XML with Attributes ---")

        guard let data = xmlString.data(using: .utf8) else {
            return []
        }

        let parser = XMLParser(data: data)
        parser.delegate = self

        parser.parse()

        print("Parsed \(products.count) products")

        return products
    }

    func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String: String] = [:]) {
        currentElement = elementName

        if elementName == "product" {
            currentId = attributeDict["id"] ?? ""
            currentCategory = attributeDict["category"] ?? ""
            print("  Found product: id=\(currentId), category=\(currentCategory)")
        }
    }

    func parser(_ parser: XMLParser, foundCharacters string: String) {
        let trimmed = string.trimmingCharacters(in: .whitespacesAndNewlines)
        if !trimmed.isEmpty {
            switch currentElement {
            case "name":
                currentName = trimmed
            case "price":
                currentPrice = trimmed
            default:
                break
            }
        }
    }

    func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
        if elementName == "product" {
            let price = Double(currentPrice) ?? 0.0
            let product = Product(id: currentId, category: currentCategory, name: currentName, price: price)
            products.append(product)

            // Reset
            currentId = ""
            currentCategory = ""
            currentName = ""
            currentPrice = ""
        }
    }
}

// 4. Parse Nested XML
struct Address {
    let street: String
    let city: String
    let state: String
    let zip: String
}

struct Person {
    let name: String
    let age: Int
    let address: Address
}

class PersonParser: NSObject, XMLParserDelegate {
    var people: [Person] = []
    var currentElement: String = ""
    var currentName: String = ""
    var currentAge: String = ""
    var currentStreet: String = ""
    var currentCity: String = ""
    var currentState: String = ""
    var currentZip: String = ""
    var inAddress = false

    func parsePeople(xmlString: String) -> [Person] {
        print("\n--- Parse Nested XML ---")

        guard let data = xmlString.data(using: .utf8) else {
            return []
        }

        let parser = XMLParser(data: data)
        parser.delegate = self

        parser.parse()

        print("Parsed \(people.count) people")

        return people
    }

    func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String: String] = [:]) {
        currentElement = elementName

        if elementName == "address" {
            inAddress = true
        }
    }

    func parser(_ parser: XMLParser, foundCharacters string: String) {
        let trimmed = string.trimmingCharacters(in: .whitespacesAndNewlines)
        if !trimmed.isEmpty {
            if inAddress {
                switch currentElement {
                case "street":
                    currentStreet = trimmed
                case "city":
                    currentCity = trimmed
                case "state":
                    currentState = trimmed
                case "zip":
                    currentZip = trimmed
                default:
                    break
                }
            } else {
                switch currentElement {
                case "name":
                    currentName = trimmed
                case "age":
                    currentAge = trimmed
                default:
                    break
                }
            }
        }
    }

    func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
        if elementName == "address" {
            inAddress = false
        }

        if elementName == "person" {
            let age = Int(currentAge) ?? 0
            let address = Address(street: currentStreet, city: currentCity, state: currentState, zip: currentZip)
            let person = Person(name: currentName, age: age, address: address)
            people.append(person)

            print("  Person: \(person.name) from \(person.address.city)")

            // Reset
            currentName = ""
            currentAge = ""
            currentStreet = ""
            currentCity = ""
            currentState = ""
            currentZip = ""
        }
    }
}

// 5. Parse XML from File
class FileXMLParser {

    static func parseXMLFromFile(filePath: String) {
        print("\n--- Parse XML from File ---")

        // First, create a sample XML file
        let sampleXML = """
        <?xml version="1.0" encoding="UTF-8"?>
        <catalog>
            <book>
                <title>Swift Programming</title>
                <author>John Smith</author>
                <year>2024</year>
                <price>49.99</price>
            </book>
            <book>
                <title>iOS Development</title>
                <author>Jane Doe</author>
                <year>2023</year>
                <price>39.99</price>
            </book>
        </catalog>
        """

        try? sampleXML.write(to: URL(fileURLWithPath: filePath), atomically: true, encoding: .utf8)
        print("Created sample XML file: \(filePath)")

        // Parse from file
        guard let data = try? Data(contentsOf: URL(fileURLWithPath: filePath)) else {
            print("Could not read file")
            return
        }

        let parser = XMLParser(data: data)
        let bookParser = BookParser()
        parser.delegate = bookParser

        if parser.parse() {
            print("\nSuccessfully parsed from file")
        }
    }
}

// 6. Parse XML with Namespaces
class NamespaceParser: NSObject, XMLParserDelegate {

    func parseWithNamespaces(xmlString: String) {
        print("\n--- Parse XML with Namespaces ---")

        guard let data = xmlString.data(using: .utf8) else {
            return
        }

        let parser = XMLParser(data: data)
        parser.delegate = self
        parser.shouldProcessNamespaces = true

        parser.parse()
    }

    func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String: String] = [:]) {
        print("Element: \(elementName)")

        if let uri = namespaceURI {
            print("  Namespace URI: \(uri)")
        }

        if let qname = qName {
            print("  Qualified name: \(qname)")
        }
    }

    func parser(_ parser: XMLParser, didStartMappingPrefix prefix: String, toURI namespaceURI: String) {
        print("Namespace mapping: \(prefix) -> \(namespaceURI)")
    }
}

// 7. Parse Large XML with Streaming
class StreamingXMLParser: NSObject, XMLParserDelegate {
    var elementCount = 0
    var maxElements = 0

    func parseStreaming(xmlString: String, maxElements: Int = 10) {
        print("\n--- Streaming XML Parsing ---")

        self.maxElements = maxElements
        elementCount = 0

        guard let data = xmlString.data(using: .utf8) else {
            return
        }

        let parser = XMLParser(data: data)
        parser.delegate = self

        parser.parse()

        print("Processed \(elementCount) elements (stopped at \(maxElements))")
    }

    func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String: String] = [:]) {
        elementCount += 1

        if elementCount <= maxElements {
            print("  Element \(elementCount): \(elementName)")
        }

        if elementCount >= maxElements {
            parser.abortParsing()
        }
    }
}

// 8. Parse XML with CDATA
class CDATAParser: NSObject, XMLParserDelegate {

    func parseWithCDATA(xmlString: String) {
        print("\n--- Parse XML with CDATA ---")

        guard let data = xmlString.data(using: .utf8) else {
            return
        }

        let parser = XMLParser(data: data)
        parser.delegate = self

        parser.parse()
    }

    func parser(_ parser: XMLParser, foundCDATA CDATABlock: Data) {
        if let cdataString = String(data: CDATABlock, encoding: .utf8) {
            print("Found CDATA:")
            print("  \(cdataString)")
        }
    }
}

// 9. XML to Dictionary Conversion
class XMLToDictionary {

    static func convertToDictionary(xmlString: String) -> [String: Any]? {
        print("\n--- XML to Dictionary Conversion ---")

        guard let data = xmlString.data(using: .utf8) else {
            return nil
        }

        do {
            let plist = try PropertyListSerialization.propertyList(from: data, options: [], format: nil)

            if let dict = plist as? [String: Any] {
                print("Converted to dictionary:")
                print(dict)
                return dict
            }

        } catch {
            print("Error: \(error)")
        }

        return nil
    }
}

// 10. Parse RSS Feed
struct RSSItem {
    let title: String
    let link: String
    let description: String
    let pubDate: String
}

class RSSParser: NSObject, XMLParserDelegate {
    var items: [RSSItem] = []
    var currentElement: String = ""
    var currentTitle: String = ""
    var currentLink: String = ""
    var currentDescription: String = ""
    var currentPubDate: String = ""
    var inItem = false

    func parseRSS(xmlString: String) -> [RSSItem] {
        print("\n--- Parse RSS Feed ---")

        guard let data = xmlString.data(using: .utf8) else {
            return []
        }

        let parser = XMLParser(data: data)
        parser.delegate = self

        parser.parse()

        print("Parsed \(items.count) RSS items")

        return items
    }

    func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String: String] = [:]) {
        currentElement = elementName

        if elementName == "item" {
            inItem = true
        }
    }

    func parser(_ parser: XMLParser, foundCharacters string: String) {
        let trimmed = string.trimmingCharacters(in: .whitespacesAndNewlines)

        if !trimmed.isEmpty && inItem {
            switch currentElement {
            case "title":
                currentTitle += trimmed
            case "link":
                currentLink += trimmed
            case "description":
                currentDescription += trimmed
            case "pubDate":
                currentPubDate += trimmed
            default:
                break
            }
        }
    }

    func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
        if elementName == "item" {
            let item = RSSItem(
                title: currentTitle,
                link: currentLink,
                description: currentDescription,
                pubDate: currentPubDate
            )
            items.append(item)

            print("  RSS Item: \(item.title)")

            // Reset
            currentTitle = ""
            currentLink = ""
            currentDescription = ""
            currentPubDate = ""
            inItem = false
        }
    }
}

// Main demonstration
func demonstrateXMLParsing() {
    print("=== macOS Swift XML Parsing Examples ===")

    // 1. Basic XML
    let basicXML = """
    <root>
        <greeting>Hello, World!</greeting>
        <message>Welcome to Swift XML parsing</message>
    </root>
    """

    let basicParser = BasicXMLParser()
    basicParser.parseXML(xmlString: basicXML)

    // 2. Books XML
    let booksXML = """
    <catalog>
        <book>
            <title>Swift Programming</title>
            <author>John Smith</author>
            <year>2024</year>
            <price>49.99</price>
        </book>
        <book>
            <title>iOS Development</title>
            <author>Jane Doe</author>
            <year>2023</year>
            <price>39.99</price>
        </book>
    </catalog>
    """

    let bookParser = BookParser()
    bookParser.parseBooks(xmlString: booksXML)

    // 3. Products with attributes
    let productsXML = """
    <products>
        <product id="1" category="electronics">
            <name>Laptop</name>
            <price>999.99</price>
        </product>
        <product id="2" category="books">
            <name>Programming Guide</name>
            <price>29.99</price>
        </product>
    </products>
    """

    let productParser = ProductParser()
    productParser.parseProducts(xmlString: productsXML)

    // 4. Nested XML
    let peopleXML = """
    <people>
        <person>
            <name>John Doe</name>
            <age>30</age>
            <address>
                <street>123 Main St</street>
                <city>New York</city>
                <state>NY</state>
                <zip>10001</zip>
            </address>
        </person>
        <person>
            <name>Jane Smith</name>
            <age>25</age>
            <address>
                <street>456 Oak Ave</street>
                <city>Los Angeles</city>
                <state>CA</state>
                <zip>90001</zip>
            </address>
        </person>
    </people>
    """

    let personParser = PersonParser()
    personParser.parsePeople(xmlString: peopleXML)

    // 5. Parse from file
    FileXMLParser.parseXMLFromFile(filePath: "/tmp/books.xml")

    // 6. RSS Feed
    let rssXML = """
    <rss>
        <channel>
            <title>Swift News</title>
            <item>
                <title>Swift 5.9 Released</title>
                <link>https://swift.org/blog/swift-5.9</link>
                <description>The latest version of Swift brings new features</description>
                <pubDate>Mon, 15 Jan 2024 10:00:00 GMT</pubDate>
            </item>
            <item>
                <title>iOS 17 Preview</title>
                <link>https://apple.com/ios17</link>
                <description>Explore the new features of iOS 17</description>
                <pubDate>Tue, 16 Jan 2024 14:30:00 GMT</pubDate>
            </item>
        </channel>
    </rss>
    """

    let rssParser = RSSParser()
    rssParser.parseRSS(xmlString: rssXML)

    // 7. Streaming XML
    let largeXML = """
    <root>
        \((1...20).map { "<item>Item \($0)</item>" }.joined(separator: "\n"))
    </root>
    """

    let streamingParser = StreamingXMLParser()
    streamingParser.parseStreaming(xmlString: largeXML, maxElements: 5)

    print("\n=== All XML Parsing Examples Completed ===")
}

// Run demonstration
demonstrateXMLParsing()