You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Swift中创建结构体/类解码指定JSON并提取report节点数据

Hey there! Let's tackle your two questions about decoding JSON in Swift—first the general approach, then the specific structure you provided with a focus on the report node.

1. General Method: Creating Structs to Decode JSON in Swift

Decoding JSON in Swift is straightforward thanks to the Codable protocol (which combines Decodable for reading JSON and Encodable for writing it). Here's the step-by-step process:

  • Map JSON structure to Swift types: For every nested object in your JSON, create a corresponding struct (structs are preferred for value types like this) that conforms to Codable.
  • Match property names: Ensure your struct's property names exactly match the JSON keys. If they don't align, use a CodingKeys enum to map them explicitly.
  • Use JSONDecoder: Convert your JSON data into Swift objects using the built-in JSONDecoder class.

Example for a simple JSON:

{"name": "Alice", "age": 30}

Corresponding struct and decoding code:

struct User: Codable {
    let name: String
    let age: Int
}

let jsonData = """
{"name": "Alice", "age": 30}
""".data(using: .utf8)!

do {
    let user = try JSONDecoder().decode(User.self, from: jsonData)
    print(user.name) // Output: Alice
} catch {
    print("Decoding error: \(error)")
}
2. Decoding Your Specific JSON (Focus on the report Node)

First, let's revisit your JSON structure:

{"earliest": "2020-10-17", "latest": "2020-10-28", "report": {"purchase": {"total": 1458600.0, "average": 121550.0, "min": 600000.0, "max": 1600.0}, "sale": {"total": 434250.0, "average": 144750.0, "min": 360000.0, "max": 29250.0}, "production": {"total": 792030, "average": 20308.46153846154, "min": 12000, "max": 29700}}}

Notice that purchase, sale, and production share the exact same structure (total, average, min, max). We can reuse a single struct for these instead of writing duplicate code. Here's how to set up your types:

// Reusable struct for purchase/sale/production metrics
struct Metric: Codable {
    let total: Double
    let average: Double
    let min: Double
    let max: Double
}

// Struct representing the full report node
struct Report: Codable {
    let purchase: Metric
    let sale: Metric
    let production: Metric
}

// Top-level struct to wrap the entire JSON response
struct ReportResponse: Codable {
    let earliest: String
    let latest: String
    let report: Report
}

Decoding and Extracting the report Node

Now, decode the JSON and pull out the report data (the core part you care about):

let jsonString = """
{"earliest": "2020-10-17", "latest": "2020-10-28", "report": {"purchase": {"total": 1458600.0, "average": 121550.0, "min": 600000.0, "max": 1600.0}, "sale": {"total": 434250.0, "average": 144750.0, "min": 360000.0, "max": 29250.0}, "production": {"total": 792030, "average": 20308.46153846154, "min": 12000, "max": 29700}}}
"""

// Convert JSON string to Data
guard let jsonData = jsonString.data(using: .utf8) else {
    fatalError("Failed to convert JSON string to data")
}

do {
    // Decode the full response
    let fullResponse = try JSONDecoder().decode(ReportResponse.self, from: jsonData)
    
    // Extract the report node
    let report = fullResponse.report
    
    // Access specific data points from the report
    print("Total purchases: \(report.purchase.total)")
    print("Average sale amount: \(report.sale.average)")
    print("Minimum production value: \(report.production.min)")
} catch {
    print("Decoding error: \(error.localizedDescription)")
}

Bonus: Directly Decode the report Node (If You Don't Need earliest/latest)

If you don't care about the top-level earliest and latest fields, you can extract the report node first before decoding:

do {
    // Convert JSON data to a dictionary
    let jsonDict = try JSONSerialization.jsonObject(with: jsonData) as? [String: Any]
    
    // Extract the report dictionary
    guard let reportDict = jsonDict?["report"] as? [String: Any] else {
        fatalError("Couldn't find the report node in JSON")
    }
    
    // Convert the report dictionary back to Data
    let reportData = try JSONSerialization.data(withJSONObject: reportDict)
    
    // Decode directly to the Report struct
    let report = try JSONDecoder().decode(Report.self, from: reportData)
    print(report)
} catch {
    print("Error: \(error.localizedDescription)")
}

This approach is less type-safe than decoding the full response, but it works if you only need the report data.

内容的提问来源于stack exchange,提问作者Jatin Menghani

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 07:44:52