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

Swift解析嵌套无结构JSON遇nil问题,请求解码方案

Swift中解码嵌套JSON并转换为数组的解决方案

这类嵌套JSON完全可以在Swift中解码,并且能转换为数组形式。以下是两种可行的实现方式:

1. 使用JSONSerialization(基础方式)

你的原代码使用try?会隐藏解析错误,导致返回nil而无法排查问题。下面是修复后的代码,同时将嵌套字典转换为数组:

JSON示例

{"1":{"1":"some text"},"2":{"1":"some text","2":"some text","3":"some text","4":"some text"},"3":{"1":" some text","2":"some text","3":"some text"},"4":{"1":"some text","2":"some text"},"5":{"1":"some text"},"6":{"1":"some text","2":"some text","3":"some text"}}

实现代码

let jsonText = """
{"1":{"1":"some text"},"2":{"1":"some text","2":"some text","3":"some text","4":"some text"},"3":{"1":" some text","2":"some text","3":"some text"},"4":{"1":"some text","2":"some text"},"5":{"1":"some text"},"6":{"1":"some text","2":"some text","3":"some text"}}
"""

do {
    guard let data = jsonText.data(using: .utf8) else {
        print("无法将字符串转换为Data")
        return
    }
    
    let jsonObject = try JSONSerialization.jsonObject(with: data)
    
    // 将解析结果转换为[String: [String: String]]类型的字典
    guard let outerDict = jsonObject as? [String: [String: String]] else {
        print("JSON结构与预期不符")
        return
    }
    
    // 按外层键排序后,提取所有内层字典组成数组
    let sortedKeys = outerDict.keys.sorted()
    let innerArray = sortedKeys.compactMap { outerDict[$0] }
    
    print("转换后的数组:\(innerArray)")
    
} catch {
    print("JSON解析错误:\(error.localizedDescription)")
}

2. 使用Codable协议(类型安全方式)

对于复杂JSON,推荐使用Swift的Codable协议,它提供类型安全的解码体验,同时可以自定义逻辑将字典转换为数组:

实现代码

import Foundation

let jsonText = """
{"1":{"1":"some text"},"2":{"1":"some text","2":"some text","3":"some text","4":"some text"},"3":{"1":" some text","2":"some text","3":"some text"},"4":{"1":"some text","2":"some text"},"5":{"1":"some text"},"6":{"1":"some text","2":"some text","3":"some text"}}
"""

// 自定义动态键,用于处理JSON中的字符串键
struct DynamicKey: CodingKey {
    let stringValue: String
    init?(stringValue: String) { self.stringValue = stringValue }
    var intValue: Int? { nil }
    init?(intValue: Int) { nil }
}

// 内层数据模型
struct InnerItem: Codable {
    let content: [String: String]
    
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: DynamicKey.self)
        var contentDict = [String: String]()
        for key in container.allKeys {
            contentDict[key.stringValue] = try container.decode(String.self, forKey: key)
        }
        self.content = contentDict
    }
}

// 外层数据模型,自动转换为数组
struct OuterData: Codable {
    let items: [InnerItem]
    
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: DynamicKey.self)
        // 按外层键排序,保证数组顺序与JSON中的键顺序一致
        let sortedKeys = container.allKeys.sorted { $0.stringValue < $1.stringValue }
        items = try sortedKeys.map { try container.decode(InnerItem.self, forKey: $0) }
    }
}

// 解码执行
do {
    guard let data = jsonText.data(using: .utf8) else {
        print("无法转换为Data")
        return
    }
    
    let result = try JSONDecoder().decode(OuterData.self, from: data)
    print("Codable转换后的数组:\(result.items)")
    
    // 访问具体元素示例
    if let firstItem = result.items.first {
        print("第一个元素的内容:\(firstItem.content)")
    }
    
} catch {
    print("Codable解码错误:\(error.localizedDescription)")
}

说明

  • 两种方式都能将嵌套JSON转换为数组,其中Codable方式更适合长期维护,类型安全且扩展性强。
  • 排序步骤是可选的,如果不需要按外层键排序,可以直接提取outerDict.values转换为数组(注意Swift字典是无序的,默认顺序不固定)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 15:55:25