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

Swift:applicationSupportDirectory读写JSON文件解码类型不匹配问题

问题:单个Event对象保存后解码为数组时出现类型不匹配错误

错误信息

typeMismatch(Swift.Array<Any>, Swift.DecodingError.Context(codingPath: [], debugDescription: "Expected to decode Array<Any> but found a dictionary instead.", underlyingError: nil))

相关代码

结构体定义

struct Event: Codable, Identifiable{
    var id: Int
    var name: String
    var organization: String
    var location: String
    var description: String
    
    private var imageName: String
    
    var image: Image{
        Image(imageName)
    }
    
    private var coordinates: Coordinates
    
    var locationCoordinate: CLLocationCoordinate2D {
        CLLocationCoordinate2D(
            latitude: coordinates.latitude,
            longitude: coordinates.longitude)
    }
    
    init(id: Int, name: String, organization: String, location: String, description: String, imageName: String, coordinates: Coordinates) {
        self.id = id
        self.name = name
        self.organization = organization
        self.location = location
        self.description = description
        self.imageName = imageName
        self.coordinates = coordinates
    }
    
}

struct Coordinates: Hashable, Codable {
    var latitude: Double
    var longitude: Double
}

保存Event的代码

func saveDataToSupportDirectory( event: Event) {
   
    do {
        let fileURL = try FileManager.default
            .url(for: .applicationSupportDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
            .appendingPathComponent("eventData.json")

        try JSONEncoder().encode(event).write(to: fileURL)
        } catch {
            print(error)
        }
}

读取数据的代码

var events: [Event] = load("eventData.json")

func load<T: Decodable>(_ filename: String) -> T {
    let data: Data

    //Load the file into data
    do {
        let fileURL = try FileManager.default
            .url(for: .applicationSupportDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
            .appendingPathComponent("eventData.json")
        data = try Data(contentsOf: fileURL)
    } catch {
        fatalError("Couldn't load data")
    }
    
    do{
        return try JSONDecoder().decode(T.self, from: data)
    }
    catch{
        print(error)
        fatalError("Couldn't decode data")
    }

}

问题原因

保存的是单个Event对象,但读取时尝试解码为**[Event]数组**,JSON结构不匹配导致类型错误——文件里是单个字典(对应Event),但解码时期望的是数组(对应[Event])。

解决方案

两种修正方式二选一即可:

方案1:修改保存逻辑,存储数组

如果需要支持多个Event,修改保存函数为接收并编码数组:

func saveDataToSupportDirectory(events: [Event]) {
    do {
        let fileURL = try FileManager.default
            .url(for: .applicationSupportDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
            .appendingPathComponent("eventData.json")

        try JSONEncoder().encode(events).write(to: fileURL)
    } catch {
        print(error)
    }
}

调用时传入数组,比如saveDataToSupportDirectory(events: [yourEvent]),读取代码无需修改。

方案2:修改读取逻辑,解码单个对象

如果只需要存储单个Event,调整读取的变量类型:

// 将数组类型改为单个Event类型
var event: Event = load("eventData.json")

此时load函数会自动推断泛型T为Event,匹配文件中的单个对象结构。

查看applicationSupportDirectory目录的方法

在Xcode中运行应用后:

  • 打开Window > Devices and Simulators
  • 选中目标设备和应用,点击Download Container...导出容器文件
  • 右键导出的容器文件,选择Show Package Contents
  • 导航到AppData/Library/Application Support即可找到eventData.json

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 15:40:21