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
相关产品推荐
相关产品推荐

