ios - 解析不同类型的 json 响应

标签 ios json swift alamofire

我有一个像这样的 json 响应......

{
    "message_code": 1,
    "orderCount": 52,
    "productCount": 5,
    "outstandingPayment": [],

 "pendingOrder": [
        {
            "order_id": 1,
            "grand_total": 67.85
             "customer_name": “xcvv”
            "mobile_number": 2147483647
        },
    ],
    "bestWishes": [
        {
            "customer_id": 1,
            "birth_date": "2018-02-02",
            "type": "birth_date",
            "customer_name": “xcvv”,
            "mobile_number": 2147483647
        },
        {
            "customer_id": 1,
            "anniversary_date": "2018-02-02",
            "type": "anniversary_date",
            "customer_name": “sdfs”,
            "mobile_number": 2147483647
        }
    ]
}

为了解析pendingOrder,我制作了一个这样的结构:

struct PendingOrder: Codable {
    let order_id: Int
    let grand_total: Double
    let customer_name: String
    let mobileNo: Int

    init(order_id : Int, grand_total: Double, customer_name: String, mobileNo: Int) {
        self.order_id = order_id
        self.grand_total = grand_total
        self.customer_name = customer_name
        self.mobileNo = mobileNo
    }
}

但是我如何为 bestWishes 创建一个结构,因为每个字典都有不同的数据,即第一个字典有一个字段 birth_date 而第二个字典有一个字段 周年纪念日...?

编辑:在发出 Alamofire 请求时,这就是我解析每个数据并将它们分配给结构的方式。

  if let bestWishes = result["bestWishes"] as? [[String:Any]] {
    for anItem in bestWishes {
      guard let customerId = anItem["customer_id"] as? Int,
            let birthdate = anItem["birth_date"] as? String,
            let customerName = anItem["customer_name"] as? String,
            let mobNo = anItem["mobile_number"] as? Int,
            let anniversaryDate = anItem["anniversary_date"] as? String,
            let type = anItem["type"] as? String
                 else {continue}

           let bestWishes = BestWishes(customer_id: customerId, birthDate: birthdate, type: type, customer_name: customerName, mobileNo: mobNo, anniversaryDate: anniversaryDate)

           self.bestWishesArr.append(bestWishes)

最佳答案

首先,当使用 Codable 时,基本上您不需要初始化程序。

如果没有自定义初始化程序(与 Codable 相关),最合适的解决方案是将两个日期都声明为可选

struct BestWish: Codable {

        private enum CodingKeys : String, CodingKey {
            case customerID = "customer_id"
            case birthDate = "birth_date"
            case anniversaryDate = "anniversary_date"
            case type
            case customerName = "customer_name"
            case mobileNumber = "mobile_number"
        }
    let customerID: Int
    let birthDate: String?
    let anniversaryDate: String?
    let type: String
    let customerName : String
    let mobileNumber: Int
}

使用自定义初始化程序声明一个属性date并根据类型解码anniversarybirth

struct BestWish: Decodable {

    private enum CodingKeys : String, CodingKey {
        case customerID = "customer_id"
        case birthDate = "birth_date"
        case anniversaryDate = "anniversary_date"
        case type
        case customerName = "customer_name"
        case mobileNumber = "mobile_number"
    }
    let customerID: Int
    let date: Date
    let type: String
    let customerName : String
    let mobileNumber: Int

    public init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        customerID = try container.decode(Int.self, forKey: .customerID)
        type = try container.decode(String.self, forKey: .type)
        if type == "anniversary_date" {
            date = try container.decode(Date.self, forKey: .anniversaryDate)
        } else {
            date = try container.decode(Date.self, forKey: .birthDate)
        }
        customerName = try container.decode(String.self, forKey: .customerName)
        mobileNo = try container.decode(Int.self, forKey: .mobileNumber)
    }
}

您可以通过给定的 type 属性区分日期。


要同时解码根对象,您需要一个伞形结构

struct Root : Decodable {
    // let pendingOrder : [PendingOrder]
    let bestWishes : [BestWish]
}

您必须从 Alamofire 请求中获取 Data 格式的 JSON 字符串,而不是反序列化字典,以将其传递给 JSONDecoder

do {
    let decoder = JSONDecoder()
    let formatter = DateFormatter()
    formatter.dateFormat = "yyyy-MM-dd"
    decoder.dateDecodingStrategy = .formatted(formatter)
    let result = try decoder.decode(Root.self, from: data)
    print(result)
} catch { print(error) }

编辑:我添加了代码以将两个日期解码为Date

关于ios - 解析不同类型的 json 响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48203822/

相关文章:

ios - 当键盘出现在 iOS (Cordova) 上时如何调整 Web View 的大小

ios - 我可以在 drawRect 方法之外绘制圆形、矩形、直线等形状吗

json - 如何使用 rails format.json

ios - 使用来自 API 的 JSON 填充单元格

ios - 如何在 iOS 图表上正确显示底轴 (xVals) 上的标签?

objective-c - 如何在 iOS 中创建旋转轮控件?

android - Gson fromJson() 返回具有空属性的对象

swift - 如何在 firebase 中非实时加载数据?

ios - 如何从多个选定行中获取数据并显示在另一个 VC tableview 单元格 Swift4

ios - 为什么我的 SearchController 只匹配第一个字符?