You need to enable JavaScript to run this app. 如何不创建顶层结构直接将JSON嵌套层数据解码为Swift结构体?
优惠活动
大模型
产品
解决方案
定价
更多

如何不创建顶层结构直接将JSON嵌套层数据解码为Swift结构体?

问题解答

问题1:能否直接解码嵌套对象、跳过顶层response结构?

可以,不需要额外定义包含顶层字段的包装结构体,直接操作Decoder的容器即可实现嵌套层数据的直接解码。

问题2:能否先校验顶层字段存在性再执行解码?

完全可以,正好适配你提到的「要么返回response要么返回error」的接口逻辑,校验逻辑可以和解码逻辑合并实现。


实现代码

1. 基础定义

首先定义你需要的业务结构体和错误结构体,不需要包含任何顶层字段:

// 业务数据结构体示例,对应response嵌套层的结构
struct User: Decodable {
    let name: String
    let id: Int
}

// 接口错误结构体示例,对应error嵌套层的结构
struct APIError: Decodable, Error {
    let code: Int
    let message: String
}

// 顶层字段的CodingKeys,不需要绑定到任何结构体
private enum TopCodingKeys: String, CodingKey {
    case response, error
}

2. 基础解码实现

直接读取顶层容器判断字段类型,再解码对应嵌套层数据:

let jsonData: Data = ... // 接口返回的原始数据
let decoder = JSONDecoder()

do {
    // 读取顶层字典容器
    let topContainer = try decoder.container(keyedBy: TopCodingKeys.self)
    // 优先判断是否存在错误字段
    if topContainer.contains(.error) {
        let apiError = try topContainer.decode(APIError.self, forKey: .error)
        // 处理业务错误逻辑
        print("接口错误:\(apiError.message)")
    } 
    // 再判断是否存在业务数据字段
    else if topContainer.contains(.response) {
        let user = try topContainer.decode(User.self, forKey: .response)
        // 直接使用解码得到的业务对象,无需处理顶层结构
        print("用户ID:\(user.id),用户名:\(user.name)")
    } 
    // 两个字段都不存在的异常场景处理
    else {
        throw NSError(domain: "APIParser", code: -1, userInfo: [NSLocalizedDescriptionKey: "响应格式非法"])
    }
} catch {
    // 处理解码失败等通用异常
    print("解析失败:\(error.localizedDescription)")
}

3. 通用封装(可选)

如果所有接口都是这个返回结构,可以封装为泛型方法简化调用:

func decodeAPIData<T: Decodable>(_ type: T.Type, from data: Data) throws -> T {
    let decoder = JSONDecoder()
    let topContainer = try decoder.container(keyedBy: TopCodingKeys.self)
    // 存在错误则直接抛出
    if let apiError = try? topContainer.decode(APIError.self, forKey: .error) {
        throw apiError
    }
    // 解码业务数据返回
    return try topContainer.decode(T.self, forKey: .response)
}

// 调用示例
do {
    let user = try decodeAPIData(User.self, from: jsonData)
    // 直接使用user对象
} catch let error as APIError {
    // 处理业务错误
} catch {
    // 处理解析错误
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.20 12:36:04