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

Swift中如何从JSON解析的Dimensions字典提取字符串数组?

问题与解决方案

需求

解析包含Dimensions(字典数组)和Measures(字符串数组)的JSON,已编写对应Codable模型,解析完成后需将Dimensions中的所有键提取为与Measures格式一致的字符串数组。

原始JSON

{"Dimensions":[{"Channel":"VARCHAR"},{"Indication":"VARCHAR"},{"LOT":"VARCHAR"},{"Monthly":"DATE"},{"Yearly":"VARCHAR"},{"Quarterly":"DATE"},{"Parameter_Classification":"VARCHAR"},{"Parameter_Type_1":"VARCHAR"},{"Parameter_Type_2":"VARCHAR"},{"Parameter_Type_3":"VARCHAR"},{"Payer_Type":"VARCHAR"},{"Product":"VARCHAR"},{"Project_Name":"VARCHAR"},{"Regime":"VARCHAR"},{"Region":"VARCHAR"},{"Scenario":"VARCHAR"},{"Trial_Name":"VARCHAR"}],"Measures":["ANSP","ASP","Demand units","DOH","EPI","Ex Factory","Gross sales","Inventory Units","Market Share","Net sales","NPS PAP","Patients","Revenue","TRx","Units","WAC"]}

已实现的Codable模型

struct Welcome: Codable {
    let dimensions: [Dimension]
    let measures: [String]

    enum CodingKeys: String, CodingKey {
        case dimensions = "Dimensions"
        case measures = "Measures"
    }
}

struct Dimension: Codable {
    let channel, indication, lot, monthly: String?
    let yearly, quarterly, parameterClassification, parameterType1: String?
    let parameterType2, parameterType3, payerType, product: String?
    let projectName, regime, region, scenario: String?
    let trialName: String?

    enum CodingKeys: String, CodingKey {
        case channel = "Channel"
        case indication = "Indication"
        case lot = "LOT"
        case monthly = "Monthly"
        case yearly = "Yearly"
        case quarterly = "Quarterly"
        case parameterClassification = "Parameter_Classification"
        case parameterType1 = "Parameter_Type_1"
        case parameterType2 = "Parameter_Type_2"
        case parameterType3 = "Parameter_Type_3"
        case payerType = "Payer_Type"
        case product = "Product"
        case projectName = "Project_Name"
        case regime = "Regime"
        case region = "Region"
        case scenario = "Scenario"
        case trialName = "Trial_Name"
    }
}

现有解析方法

private func decodeJson(welcomeString: String) {
    let data = Data(welcomeString.utf8)
    do {
        let infoType = try JSONDecoder().decode(Welcome.self, from: data)
//        print(infoType.dimensions)
//        print(infoType.measures)
    } catch let error {
        print(error)
    }
}

解决方案

方法一:利用模型CodingKeys提取(推荐)

由于Dimension的CodingKeys已映射JSON中所有可能的键名,只需给CodingKeys添加CaseIterable协议,即可直接提取所有键的原始名称:

  1. 修改Dimension.CodingKeys,添加CaseIterable协议:
enum CodingKeys: String, CodingKey, CaseIterable {
    case channel = "Channel"
    case indication = "Indication"
    case lot = "LOT"
    case monthly = "Monthly"
    case yearly = "Yearly"
    case quarterly = "Quarterly"
    case parameterClassification = "Parameter_Classification"
    case parameterType1 = "Parameter_Type_1"
    case parameterType2 = "Parameter_Type_2"
    case parameterType3 = "Parameter_Type_3"
    case payerType = "Payer_Type"
    case product = "Product"
    case projectName = "Project_Name"
    case regime = "Regime"
    case region = "Region"
    case scenario = "Scenario"
    case trialName = "Trial_Name"
}
  1. 修改解析方法,提取键数组:
private func decodeJson(welcomeString: String) {
    let data = Data(welcomeString.utf8)
    do {
        let infoType = try JSONDecoder().decode(Welcome.self, from: data)
        // 提取Dimensions的所有键名,格式与Measures一致
        let dimensionKeys = Dimension.CodingKeys.allCases.map { $0.rawValue }
        print(dimensionKeys)
        print(infoType.measures)
    } catch let error {
        print(error)
    }
}

方法二:直接解析原始JSON(兼容模型未覆盖的键)

如果担心JSON中存在模型未定义的键,可直接解析原始JSON数据提取键:

private func decodeJson(welcomeString: String) {
    let data = Data(welcomeString.utf8)
    do {
        // 解析为原始JSON对象
        guard let json = try JSONSerialization.jsonObject(with: data) as? [String: Any],
              let dimensions = json["Dimensions"] as? [[String: Any]] else {
            return
        }
        // 提取所有键并去重
        let dimensionKeys = dimensions.flatMap { $0.keys }.unique()
        print(dimensionKeys)
        
        // 同时解析模型获取Measures
        if let infoType = try? JSONDecoder().decode(Welcome.self, from: data) {
            print(infoType.measures)
        }
    } catch let error {
        print(error)
    }
}

// 给数组添加去重扩展
extension Array where Element: Hashable {
    func unique() -> [Element] {
        var seen = Set<Element>()
        return filter { seen.insert($0).inserted }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 05:06:34