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

如何使用Codable协议解析含嵌套JSON字符串的JSON数据

问题分析与解决方案

首先,咱们来拆解下你遇到的解析错误根源:

你的原始JSON里,nativeId字段的值是一个被转义包裹的JSON字符串(比如"{\"app\":\"1234/Car/Native_App\",\"web\":\"/8888/Car/Native_Car_Desktop\"}"),而你当前的代码犯了两个关键错误:

  1. 设置了decoder.dataDecodingStrategy = .deferredToData,这个策略会让JSONDecoder尝试把字符串解码成Data类型,但nativeId是普通的JSON字符串,不是Base64编码的二进制数据,直接触发格式错误。
  2. 即使去掉这个策略,把nativeId定义为String?只能拿到原始字符串,没法直接使用里面的app和web字段,不符合实际开发需求。

另外你提供的原始JSON里web字段的引号有语法错误,正确的JSON应该是:

{
  "yearOfManufacture":"20/9/2018",
  "carSize":8,
  "isNew":true,
  "carAssets":[
    {
      "color":"5761807993001",
      "nativeId":"{\"app\":\"1234/Car/Native_App\",\"web\":\"/8888/Car/Native_Car_Desktop\"}"
    }
  ]
}

方案1:仅解析为字符串(快速修复)

如果暂时只需要把nativeId当作字符串存储,不需要解析内部字段,只需要移除错误的解码策略即可:

struct Cars: Codable {
    var yearOfManufacture: String?
    var carSize: Int = 0
    var isNew: Bool = true
    var carAssets: [CarAssests]?
}

struct CarAssests: Codable {
    var color: String?
    var nativeId: String?
}

// 解析代码
let decoder = JSONDecoder()
// 移除这行错误的策略:decoder.dataDecodingStrategy = .deferredToData
if let jsonData = jsonString.data(using: .utf8) {
    do {
        let assets = try decoder.decode(Cars.self, from: jsonData)
        print(assets)
        
        // 如果后续需要解析nativeId内部字段,可以手动二次解码
        if let nativeIdStr = assets.carAssets?.first?.nativeId,
           let nativeData = nativeIdStr.data(using: .utf8) {
            let nativeDict = try JSONSerialization.jsonObject(with: nativeData) as? [String: String]
            print("app: \(nativeDict?["app"] ?? "")")
            print("web: \(nativeDict?["web"] ?? "")")
        }
    } catch {
        print(error) // 打印完整错误,别只看localizedDescription,能拿到更详细的报错信息
    }
}

方案2:直接解析为结构体(推荐)

如果需要直接使用nativeId里的app和web字段,咱们可以自定义解码逻辑,把嵌套的JSON字符串直接解析成结构体:

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

struct Cars: Codable {
    var yearOfManufacture: String?
    var carSize: Int = 0
    var isNew: Bool = true
    var carAssets: [CarAssests]?
}

struct CarAssests: Codable {
    var color: String?
    var nativeId: NativeId?
    
    // 自定义解码逻辑
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        color = try container.decodeIfPresent(String.self, forKey: .color)
        
        // 先把nativeId解码成字符串,再转成Data,最后解码成NativeId结构体
        if let nativeIdStr = try container.decodeIfPresent(String.self, forKey: .nativeId),
           let nativeData = nativeIdStr.data(using: .utf8) {
            nativeId = try JSONDecoder().decode(NativeId.self, from: nativeData)
        } else {
            nativeId = nil
        }
    }
    
    enum CodingKeys: String, CodingKey {
        case color, nativeId
    }
}

// 对应nativeId内部的结构
struct NativeId: Codable {
    var app: String?
    var web: String?
}

步骤2:正常解析使用

let decoder = JSONDecoder()
if let jsonData = jsonString.data(using: .utf8) {
    do {
        let assets = try decoder.decode(Cars.self, from: jsonData)
        print("app字段值:\(assets.carAssets?.first?.nativeId?.app ?? "")")
        print("web字段值:\(assets.carAssets?.first?.nativeId?.web ?? "")")
    } catch {
        print(error) // 打印完整错误信息,方便排查问题
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:44:08