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

如何使用Swift 4.0 Codable过滤JSON解码中的无效数据

用Swift 4.0 Codable过滤无效数据的方案

针对你的需求——过滤掉no值小于等于0的条目,我给你两种实用的实现方式,都是基于Codable的类型安全特性来做的:


方式一:先解码完整数组,再过滤有效数据

这种方式和你之前用Alamofire处理的逻辑最接近:先把所有数据解码成模型数组,再用filter筛选出符合条件的条目。

步骤1:定义完整的模型结构

首先要把JSON的外层结构也定义成Codable模型,覆盖顶层的data、里面的result、total_count和list:

// 顶层API响应模型
struct ApiResponse: Codable {
    let data: ResponseData
}

// data字段对应的模型
struct ResponseData: Codable {
    let result: Int
    let totalCount: Int
    let list: [SampleModel]
    
    // 处理JSON蛇形命名到Swift驼峰命名的映射
    enum CodingKeys: String, CodingKey {
        case result
        case totalCount = "total_count"
        case list
    }
}

// 单个条目模型
struct SampleModel: Codable {
    let no: Int
    let category: Int
    let templateSeq: Int
    
    enum CodingKeys: String, CodingKey {
        case no
        case category
        case templateSeq = "template_seq"
    }
}

步骤2:解码后过滤数据

解码完成后,直接对list数组进行过滤即可:

if let jsonData = jsonString.data(using: .utf8) {
    do {
        let apiResponse = try JSONDecoder().decode(ApiResponse.self, from: jsonData)
        // 过滤掉no<=0的无效条目
        let validSamples = apiResponse.data.list.filter { $0.no > 0 }
        print("有效条目数量:\(validSamples.count)")
        // 在这里使用validSamples即可
    } catch {
        print("解码失败:\(error.localizedDescription)")
    }
}

这种方式简单直接,和你之前手动遍历字典的逻辑一致,而且全程类型安全,不需要繁琐的强制类型转换。


方式二:在解码过程中直接过滤(更优雅)

如果想把过滤逻辑整合到解码流程里,可以自定义ResponseData的解码方法,在解码list的时候就直接过滤掉无效条目:

修改后的ResponseData模型

struct ResponseData: Codable {
    let result: Int
    let totalCount: Int
    let list: [SampleModel]
    
    enum CodingKeys: String, CodingKey {
        case result
        case totalCount = "total_count"
        case list
    }
    
    // 自定义解码逻辑
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        // 先解码基础字段
        result = try container.decode(Int.self, forKey: .result)
        totalCount = try container.decode(Int.self, forKey: .totalCount)
        
        // 先解码所有条目,再过滤
        let allSamples = try container.decode([SampleModel].self, forKey: .list)
        // 只保留no>0的有效条目
        list = allSamples.filter { $0.no > 0 }
    }
}

解码代码

此时解码后直接拿到的apiResponse.data.list就是已经过滤好的有效数据:

if let jsonData = jsonString.data(using: .utf8) {
    do {
        let apiResponse = try JSONDecoder().decode(ApiResponse.self, from: jsonData)
        print("已过滤的有效条目数量:\(apiResponse.data.list.count)")
        // 直接使用apiResponse.data.list即可
    } catch {
        print("解码失败:\(error.localizedDescription)")
    }
}

额外说明:如果想让无效条目抛出解码错误

如果你希望当存在no<=0的条目时,直接触发解码错误(而不是跳过),可以在SampleModel的自定义解码方法里添加校验:

struct SampleModel: Codable {
    let no: Int
    let category: Int
    let templateSeq: Int
    
    enum CodingKeys: String, CodingKey {
        case no
        case category
        case templateSeq = "template_seq"
    }
    
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        no = try container.decode(Int.self, forKey: .no)
        category = try container.decode(Int.self, forKey: .category)
        templateSeq = try container.decode(Int.self, forKey: .templateSeq)
        
        // 校验no的有效性,无效则抛出解码错误
        guard no > 0 else {
            throw DecodingError.dataCorruptedError(
                forKey: .no,
                in: container,
                debugDescription: "无效的no值:\(no),必须大于0"
            )
        }
    }
}

这种情况下,如果JSON里存在no<=0的条目,整个解码过程会抛出错误,你可以在catch块里针对性处理这种情况。


内容的提问来源于stack exchange,提问作者Michael Park

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:12:59