首页 > 解决方案 > 如何将包含数组的 Swift 对象自定义编码为 JSON?

问题描述

我是一名新手开发人员,正在编写一个 iOS 应用程序,该应用程序允许用户在一段录制的音乐中定义和重播多个“段落”,每个段落多次。

我的类 'Piece' 是一个 Observable 对象,它当前仅包含已发布的 var 'passages'(包含用户希望重播的段落详细信息的记录数组)。虽然 Piece 的唯一成员现在是一个“通道”数组,但我希望 Piece 最终会有更多成员,而不是数组。

我希望能够将用户定义的每个 Piece 保存为 JSON 文件。因为 'Piece' 是一个可观察的对象,所以它不符合 Codable 除非我编写自定义编码和解码函数。到目前为止,我一直无法找到任何示例代码来说明如何编码一个对象(在我的情况下为“Piece”),而该对象又包含一个自定义对象数组(在我的情况下为“Passage”),这些对象有多个特性。

下面显示了我的“Piece”和“Passage”代码的相关部分。

class Piece: ObservableObject, Codable {

    @Published var passages = [Passage]()
    
    enum CodingKeys: CodingKey {
        case passages
    }
  
    init() { }
    
    required init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
    passages = try container.decode([Passage].self, forKey: .passages)
    }
    
    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode([Passage](), forKey: .passages)
        
    }
}
 
struct Passage: Codable, Equatable, Identifiable, Hashable {

    var id = UUID()
    var startTime: Double
    var endTime: Double
    var extraPause: Double
    var numIterations: Int
    var skipMe: Bool = false
    
    enum PassageKeys: CodingKey {
        case id, startTime, endTime, extraPause, numIterations, skipMe
    }
    
    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: PassageKeys.self)
        try container.encode(id, forKey: .id)
        try container.encode(startTime, forKey: .startTime)
        try container.encode(endTime, forKey: .endTime)
        try container.encode(extraPause, forKey: .extraPause)
        try container.encode(numIterations, forKey: .numIterations)
        try container.encode(skipMe, forKey: .skipMe)
    }
}

在我的应用程序界面中,我编写了以下按钮操作。

let url = self.getDocumentsDirectory().appendingPathComponent("X.json")
let encoder = JSONEncoder()
do {
    let data = try encoder.encode(self.piece)
        let string = String(data: data, encoding: .utf8)!
        print("Here is the string we are trying to write: \(string)")
        try string.write(to: url, atomically: true, encoding: .utf8)
   } catch {
        print(error.localizedDescription)
}

当我用几条记录填充“通道”数组然后单击触发此操作的按钮时,控制台输出显示:

Here is the string we are trying to write: {"passages":[]}

在 Passage.encode() 函数中设置断点表明该函数永远不会被调用。

谁能帮我指出正确的方向?

标签: arraysjsonswiftencode

解决方案


你应该改变

try container.encode([Passage](), forKey: .passages)

try container.encode(passages, forKey: .passages)

在你的代码中。否则,您总是试图对刚刚创建的新空数组进行编码[Passage]()


推荐阅读