ios swift处理json数据

1. 使用 Codable 协议(推荐)

基本使用

swift

复制代码
// 定义模型
struct User: Codable {
    let id: Int
    let name: String
    let email: String?
    let age: Int?
    
    // 如果键名不同,使用 CodingKeys
    private enum CodingKeys: String, CodingKey {
        case id, name, email, age
    }
}

// 解析 JSON
let jsonString = """
{
    "id": 1,
    "name": "John",
    "email": "john@example.com",
    "age": 30
}
"""

do {
    let jsonData = Data(jsonString.utf8)
    let user = try JSONDecoder().decode(User.self, from: jsonData)
    print(user.name)  // 输出: John
} catch {
    print("解码错误: \(error)")
}

// 编码为 JSON
let user = User(id: 1, name: "Jane", email: nil, age: 25)
do {
    let jsonData = try JSONEncoder().encode(user)
    let jsonString = String(data: jsonData, encoding: .utf8)
} catch {
    print("编码错误: \(error)")
}

处理嵌套 JSON

swift

复制代码
struct Post: Codable {
    let title: String
    let author: User
    let tags: [String]
}

// 自定义日期格式
struct Event: Codable {
    let name: String
    let date: Date
}

let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601
// 或自定义格式
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
decoder.dateDecodingStrategy = .formatted(formatter)

2. 使用 JSONSerialization

swift

复制代码
// 解析 JSON
let jsonString = """
{
    "name": "Swift",
    "version": 5.0
}
"""

if let data = jsonString.data(using: .utf8) {
    do {
        if let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] {
            let name = json["name"] as? String
            let version = json["version"] as? Double
            print("Name: \(name ?? ""), Version: \(version ?? 0)")
        }
    } catch {
        print("JSON 解析错误: \(error)")
    }
}

// 创建 JSON
let dict: [String: Any] = [
    "name": "iOS",
    "version": 15.0,
    "features": ["SwiftUI", "ARKit"]
]

do {
    let jsonData = try JSONSerialization.data(withJSONObject: dict, options: .prettyPrinted)
    if let jsonString = String(data: jsonData, encoding: .utf8) {
        print(jsonString)
    }
} catch {
    print("JSON 创建错误: \(error)")
}

3. 处理复杂场景

自定义解码

swift

复制代码
struct Product: Codable {
    let id: Int
    let name: String
    let price: Double
    let discountPrice: Double?
    
    // 自定义解码逻辑
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        id = try container.decode(Int.self, forKey: .id)
        name = try container.decode(String.self, forKey: .name)
        price = try container.decode(Double.self, forKey: .price)
        
        // 处理可选值
        discountPrice = try container.decodeIfPresent(Double.self, forKey: .discountPrice)
        
        // 数据验证
        if price < 0 {
            throw DecodingError.dataCorruptedError(
                forKey: .price,
                in: container,
                debugDescription: "价格不能为负数"
            )
        }
    }
}

使用 Property Wrapper

swift

复制代码
@propertyWrapper
struct DefaultEmptyString: Codable {
    var wrappedValue: String
    
    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        wrappedValue = (try? container.decode(String.self)) ?? ""
    }
}

struct Profile: Codable {
    @DefaultEmptyString var nickname: String
    @DefaultEmptyString var bio: String
}

4. 网络请求中的 JSON 处理

swift

复制代码
import Foundation

struct NetworkService {
    func fetchData<T: Decodable>(from url: URL) async throws -> T {
        let (data, response) = try await URLSession.shared.data(from: url)
        
        guard let httpResponse = response as? HTTPURLResponse,
              (200...299).contains(httpResponse.statusCode) else {
            throw URLError(.badServerResponse)
        }
        
        let decoder = JSONDecoder()
        decoder.keyDecodingStrategy = .convertFromSnakeCase  // 处理蛇形命名
        
        return try decoder.decode(T.self, from: data)
    }
}

// 使用示例
struct APIResponse<T: Codable>: Codable {
    let status: Int
    let message: String
    let data: T
}

// 调用
Task {
    do {
        let url = URL(string: "https://api.example.com/users")!
        let response: APIResponse<[User]> = try await NetworkService().fetchData(from: url)
        print(response.data)
    } catch {
        print("错误: \(error)")
    }
}

5. 使用第三方库

Swift Package Manager 添加依赖

swift

复制代码
// 在 Package.swift 中添加
dependencies: [
    .package(url: "https://github.com/SwiftyJSON/SwiftyJSON.git", from: "5.0.0")
]

SwiftyJSON 示例

swift

复制代码
import SwiftyJSON

let json = JSON(parseJSON: jsonString)
let name = json["user"]["name"].stringValue
let age = json["user"]["age"].intValue

// 安全访问
if let email = json["user"]["email"].string {
    print(email)
}

6. 最佳实践

  1. 始终使用 do-catch 处理错误

  2. 使用可选类型处理可能缺失的数据

  3. 为 API 响应创建专门的模型

  4. 使用 keyDecodingStrategy 处理命名约定

  5. 考虑使用 Result 类型

swift

复制代码
enum NetworkError: Error {
    case invalidURL
    case noData
    case decodingError
}

func parseJSON<T: Decodable>(data: Data) -> Result<T, NetworkError> {
    do {
        let decodedData = try JSONDecoder().decode(T.self, from: data)
        return .success(decodedData)
    } catch {
        return .failure(.decodingError)
    }
}

7. 性能优化技巧

swift

复制代码
// 重用 JSONDecoder/JSONEncoder
class JSONManager {
    static let shared: JSONDecoder = {
        let decoder = JSONDecoder()
        decoder.dateDecodingStrategy = .iso8601
        decoder.keyDecodingStrategy = .convertFromSnakeCase
        return decoder
    }()
}

// 使用 lazy 延迟解码
struct LazyDecoded<T: Decodable>: Decodable {
    let value: T
    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        self.value = try container.decode(T.self)
    }
}

这些方法涵盖了 Swift 中处理 JSON 的主要场景。Codable 是现代 Swift 开发中最推荐的方式,因为它类型安全、代码简洁。

相关推荐
电商API&Tina6 小时前
【电商API接口】开发者一站式电商API接入说明
大数据·数据库·人工智能·云计算·json
RickeyBoy7 小时前
独立 App 配置阿里云 CDN 记录
ios
消失的旧时光-19437 小时前
Android 面试高频:JSON 文件、大数据存储与断电安全(从原理到工程实践)
android·面试·json
白玉cfc9 小时前
接口与API设计
ios·objective-c
少云清14 小时前
IOS历史版本下载
ios
ChoSeitaku16 小时前
NO.4|protobuf网络版通讯录|httplib|JSON、XML、ProtoBuf对比
xml·json
青衫客3617 小时前
浅谈 Java 后端对象映射:从 JSON → VO → Entity 的原理与实践
java·json
qqxhb1 天前
11|结构化输出:为什么 JSON 能让系统更稳定
json·ai编程·结构化·规范模板
奶糖的次元空间1 天前
iOS 学习笔记 - SwiftUI 和 简单布局
ios·swift
小黑要努力1 天前
json-c安装以及amixer使用
linux·运维·json