【问题标题】:Decoding array based JSON in Swift在 Swift 中解码基于数组的 JSON
【发布时间】:2021-02-18 19:49:25
【问题描述】:

我有一个 WebSocket,它使用 [command, data] 的数组格式来交换消息。我正在努力使用 Swift 解码器来处理数据部分的混合格式。例如消息 #1:

["CFG",{"dimmerDelay":5000,"keyboardShortcuts":true}]

消息 #2:

["LFM",true]

我正在使用它来解码消息 #1

struct Message: Decodable {
    let command: String
    let config: Config
    
    init(from decoder: Decoder) throws {
        var container = try decoder.unkeyedContainer()
        command = try container.decode(String.self)
        config = try container.decode(Config.self)
        }
    }

struct Config: Decodable {
    let dimmerDelay: Int
    let keyboardShortcuts: Bool
    }

我真正想要的是把它拆分成一个更像这样的容器:

struct Message: Decodable {
    let command: String
    let data: String
    }

然后,如果消息是“CFG”类型,我会将数据传递给将创建 Config 对象的解码器。如果消息是“LFM”类型,我会检查以确保结果为真,如果消息是另一种类型,我会将该数据传递给另一个解码器,该解码器将创建相关的解码对象。

【问题讨论】:

    标签: arrays json swift decode


    【解决方案1】:

    有几种方法,但假设您知道所有“命令”字符串以及它们映射到的内容,您可以采用枚举方法:

    enum Message {
        case config(Config)
        case lfm(Bool)
    }
    

    要使这个可解码,你只需要一个 switch 语句:

    extension Message: Decodable {
        init(from decoder: Decoder) throws {
            var container = try decoder.unkeyedContainer()
            let command = try container.decode(String.self)
    
            switch command {
            case "CFG":
                self = .config(try container.decode(Config.self))
    
            case "LFM":
                self = .lfm(try container.decode(Bool.self))
    
            default:
                throw DecodingError.typeMismatch(Message.self,
                                                 .init(codingPath: [],
                                                       debugDescription: "Unknown command: \(command)"))
            }
        }
    }
    

    解码后,您将使用 switch 语句来确定您拥有什么:

    let message = try JSONDecoder().decode(Message.self, from: json)
    
    switch message {
    case .config(let config): handleConfig(config)
    case .lfm(let bool): handleLFM(bool)
    }
    

    【讨论】:

    • 所以是的,我有一个所有命令的枚举: enum WebsocketCommand: String { case Call = "CAL" case Config = "CFG" case ListCall = "LCL" case LivefeedMap = "LFM" case Pin = "PIN" } 现在我如何确定消息类型是什么?所以我收到消息并使用它进行解码,确定生成的消息类型是 Config、LFM 还是 LCL 等的正确方法是什么
    • 更新了你需要的 switch 语句。
    • 哇,这真的很优雅,而且比我尝试做的要容易得多!效果很好!谢谢!!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-31
    • 2021-10-24
    相关资源
    最近更新 更多