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

JSON文件解码:采用Struct还是Class管理数据更合理?

JSON解码实现方案合理性及数据管理类型选择疑问

我正在实现JSON文件解码功能,用两个struct作为数据模型,一个FriendsManager类做数据管理。作为JSON解码新手,想确认这个实现方案是否合理,还是应该用struct替代class来做数据管理?


实现代码

FriendsManager 管理类

private let JSONFriendFileName = "Friends"

class FriendsManager: ObservableObject {

    var friendsList: [FriendsList] = []
    
    init() {
        let decoder = JSONDecoder()
        decoder.keyDecodingStrategy = .convertFromSnakeCase
        decode(fileName: JSONFriendFileName, decoder: decoder)
    }
    
     func decode(fileName: String, decoder: JSONDecoder) {
        
        guard let url = Bundle.main.url(forResource: JSONFriendFileName, withExtension: "json") else {
            print("项目中不存在名为 \(JSONFriendFileName + ".json") 的文件")
            return
        }

        do {
            let data = try Data(contentsOf: url)
            let items = try decoder.decode(Friends.self, from: data)

            friendsList = items.friendsList

        } catch {
            print(error.localizedDescription)
        }
    }
}

数据模型 Struct

struct Friends: Codable {
    var friendsList: [FriendsList]
}

struct FriendsList: Codable, Identifiable {
    let name: String
    let timestamp: Int?
    let contact_info: String?
    
    let id = UUID()
    
    enum CodingKeys: String, CodingKey {
        case name, timestamp, contact_info
    }
}

数据使用示例

import SwiftUI

struct FriendsView: View {
    
    @StateObject private var friendsManager = FriendsManager()
    
    var body: some View {
        NavigationView {
            List {
                ForEach(friendsManager.friendsList) { friend in
                    Text(friend.name)
                }
            }
            .navigationTitle("好友列表")
        }
    }
}

方案分析与建议

当前方案的合理性

你的实现整体是合理的:

  • 用struct作为数据模型完全契合Swift设计理念,值类型适合存储纯数据,Codable协议在struct上的实现简洁直观,没有额外的引用管理成本。
  • FriendsManager作为ObservableObject类,配合SwiftUI的@StateObject使用,能很好地把控数据生命周期,后续如果需要修改好友列表(比如增删条目、重新加载数据),引用类型的特性可以保证所有关联视图同步获取最新状态。

是否需要用struct替代class做数据管理?

不建议替换,原因如下:

  1. SwiftUI状态管理要求:@StateObject仅支持引用类型(class),如果换成struct,需要用@State或@Binding,但多视图共享数据时,值类型的拷贝会带来状态同步问题,维护成本更高。
  2. 功能扩展性:如果后续要添加异步加载(比如从网络拉取数据)、数据持久化(比如修改后存回本地)等带副作用的逻辑,类的设计更易维护,值类型处理这类状态变化会非常繁琐。

可优化的细节

  • 给friendsList加上@Published包装器,这样列表内容变化时视图会自动刷新:
    @Published var friendsList: [FriendsList] = []
    
  • decode方法的fileName参数未被实际使用,改成用参数值获取文件,让方法更通用:
    func decode(fileName: String, decoder: JSONDecoder) {
        guard let url = Bundle.main.url(forResource: fileName, withExtension: "json") else {
            print("项目中不存在名为 \(fileName + ".json") 的文件")
            return
        }
        // 后续逻辑不变
    }
    
  • 利用convertFromSnakeCase解码策略,可以省略FriendsList的CodingKeys,自动将contact_info映射为驼峰命名的contactInfo:
    struct FriendsList: Codable, Identifiable {
        let name: String
        let timestamp: Int?
        let contactInfo: String?
        
        let id = UUID()
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 09:22:16