ios - 如何在swift中解码具有不同数据类型的不断变化的密钥
问题描述
我在将 json 解码为 Swift 中的 Codable 模型时遇到了一些问题。我从服务器得到的 json 响应看起来像这样
{
"code": 200,
"data": {
"Australia": {
"address": "1111",
"port": "443",
"proto": "udp",
"country": "au"
},
"Australia udp": {
"address": "2222",
"port": "443",
"proto": "udp",
"country": "au"
},
"Vietnam TCP": {
"address": "3333",
"port": "443",
"proto": "tcp",
"country": "vn"
},
"status": "1"
}
}
现在我找到了其他关于如何解码简单数据类型的帖子,但我找不到可以解码复杂数据类型的帖子!到目前为止我所做的是这个模型
struct ListServers: Codable {
let code: Int
let data: [String: ListServersData]
}
enum ListServersData: Codable {
case string(String)
case innerItem(ServerInfo)
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if let x = try? container.decode(String.self) {
self = .string(x)
return
}
if let x = try? container.decode(ServerInfo.self) {
self = .innerItem(x)
return
}
throw DecodingError.typeMismatch(ListServersData.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for MyValue"))
}
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case .string(let x):
try container.encode(x)
case .innerItem(let x):
try container.encode(x)
}
}
}
struct ServerInfo: Codable {
let address, port, proto, country: String
}
但这会引发错误!
我不确定如何解码,因为我有响应的附加状态
解决方案
尝试这个:
只需在某处设置一个json字符串
let json =
"""
{
"code": 200,
"data": {
"Australia": {
"address": "1111",
"port": "443",
"proto": "udp",
"country": "au"
},
"Australia udp": {
"address": "2222",
"port": "443",
"proto": "udp",
"country": "au"
},
"Vietnam TCP": {
"address": "3333",
"port": "443",
"proto": "tcp",
"country": "vn"
},
"status": "1"
}
}
"""
然后设置与上面完全相同的结构和枚举:
struct ListServers: Codable {
let code: Int
let data: [String: ListServersData]
}
enum ListServersData: Codable {
case string(String)
case innerItem(ServerInfo)
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if let x = try? container.decode(String.self) {
self = .string(x)
return
}
if let x = try? container.decode(ServerInfo.self) {
self = .innerItem(x)
return
}
throw DecodingError.typeMismatch(ListServersData.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for MyValue"))
}
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case .string(let x):
try container.encode(x)
case .innerItem(let x):
try container.encode(x)
}
}
}
struct ServerInfo: Codable {
let address, port, proto, country: String
}
然后像这样解码那个json:
let jsonData = json.data(using: .utf8)!
do {
let decoder = JSONDecoder()
let result = try decoder.decode(ListServers.self, from: jsonData)
print("Code: \(result.code)")
for (_, v) in result.data {
switch v {
case .string(let string):
print("Status: \(string)")
case .innerItem(let serverInfo):
print("Address: \(serverInfo.address)")
print("Port: \(serverInfo.port)")
print("Proto: \(serverInfo.proto)")
print("Country: \(serverInfo.country)")
}
print("=======================")
}
}
catch {
print(error)
}
这是打印出来的没有错误的内容:
Code: 200
Address: 3333
Port: 443
Proto: tcp
Country: vn
=======================
Address: 2222
Port: 443
Proto: udp
Country: au
=======================
Status: 1
=======================
Address: 1111
Port: 443
Proto: udp
Country: au
=======================
推荐阅读
- oracle - Oracle Cloud 和 Azure 之间的 VPN
- algorithm - 将 n 个值添加到空链表以便对其进行排序的时间复杂度?
- python - 如何不在python中获得重复值
- pandas - 如何避免从 DataFrame 到 CSV 的 unicode 错误?
- docker - docker compose up gving error as I need to stop mysql service ERROR: for demo_db_1 Cannot start
- python - NoReverseMatch at /login/ Reverse for 'teacher_dashboard' with arguments '({'teacher':object (2)>},)' 未找到。尝试了 1 种模式:
- docker - 层数是否对当前和未来 docker 镜像的大小、设置时间或性能有影响?
- android - 如果从 Google Play 商店下载 apk 和 obb,则无法在 android 10 设备上访问 obb 扩展文件
- python-3.x - 将 python2 混合类型 np.array 操作迁移到 python3
- xml - C# Word AddIn 编辑 CustomXmlParts