在 Swift 中解码基于 JSON 的数组
Decoding array based JSON in Swift
我有一个 WebSocket,它使用 [命令,数据] 的数组格式来交换消息。我正在努力使用 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”类型,我会检查以确保结果为真,如果消息是另一种类型,我会将该数据传递给另一个解码器,该解码器将创建相关的解码对象。
有几种方法,但假设您知道所有“命令”字符串及其映射到的内容,您可以采用枚举方法:
enum Message {
case config(Config)
case lfm(Bool)
}
要使这个 Decodable,你只需要一个 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)
}
我有一个 WebSocket,它使用 [命令,数据] 的数组格式来交换消息。我正在努力使用 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”类型,我会检查以确保结果为真,如果消息是另一种类型,我会将该数据传递给另一个解码器,该解码器将创建相关的解码对象。
有几种方法,但假设您知道所有“命令”字符串及其映射到的内容,您可以采用枚举方法:
enum Message {
case config(Config)
case lfm(Bool)
}
要使这个 Decodable,你只需要一个 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)
}