json - 如果接收到的值不匹配,则解码字典正确
问题描述
嘿,我有这个 Json 例如:
{"v":{"value1":1548303671,"value2":"invalid","value3":"invalid"}}
和模型类:
struct VersionApi: Decodable {
let data: NestedData?
let v: [String:Int?]
enum CodingKeys: String, CodingKey {
case data = "data"
case v = "v"
}
}
尝试解码时,我收到此错误消息:
debugDescription:“预期解码 Int,但找到了一个字符串/数据。”,underlyingError:nil)
我知道这意味着什么,但我不知道解决方案。我需要一本带有这种格式的 Ints 的字典:[String:Int?]
. 我试图编写一个这样的自定义初始化程序:
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
data = try values.decode(NestedData, forKey: .data)
let vID: [String:Any] = try values.decode([String:Any].self, forKey: .v)
v = try values.decode([String:Int?].self, forKey: .v)
}
然后我想浏览字典,如果Any
不是Int
,我希望它设置为nil
. 但这不起作用,因为没有候选人产生预期的类型:
没有“解码”候选者产生预期的上下文结果类型“[String:Any]”
如果值不是 Int,如何将 Int 设置为 nil?
解决方案
由于Any
不可解码,因此编译器在抱怨。您可以首先创建一个enum
(从此答案)如下来解码/编码动态类型,
enum BiType<L: Codable, R: Codable>: Codable {
case left(L)
case right(R)
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if let left = try? container.decode(L.self) {
self = .left(left)
} else if let right = try? container.decode(R.self) {
self = .right(right)
} else {
throw DecodingError
.typeMismatch(
BiType<L, R>.self,
.init(codingPath: decoder.codingPath,
debugDescription: "Expected either `\(L.self)` or `\(R.self)`"))
}
}
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case let .left(left):
try container.encode(left)
case let .right(right):
try container.encode(right)
}
}
}
现在您可以更新VersionApi
以使用该类型,
struct VersionApi: Decodable {
let data: NestedData?
let v: [String: BiType<String, Int>]
enum CodingKeys: String, CodingKey {
case data = "data"
case v = "v"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
data = try values.decode(NestedData.self, forKey: .data)
v = try values.decode([String: BiType<String, Int>].self, forKey: .v)
}
}
例子
let data = """
{"v":{"value1":1548303671,"value2":"invalid","value3":"invalid"}}
""".data(using: .utf8)!
do {
let v = try JSONDecoder().decode(VersionApi.self, from: data)
v.v.values.forEach({ (type) in
switch type {
case .left(let left):
debugPrint(left)
case .right(let right):
debugPrint(right)
}
})
} catch {
debugPrint(error)
}
输出
1548303671 "invalid" "invalid"
推荐阅读
- android - Recyclerview 滚动不顺畅并停留在前 10 个项目上
- javascript - 禁用所有键,但复制粘贴组合
- azure-functions - 不同的 Azure Functions 是否在同一个 Node.js 进程上运行?
- node.js - mongodb中的关闭连接-应用程序卡住了-好吗?
- javascript - 尝试在 AdWords 脚本中进行基本的 vlookup,但耗时太长
- python - 从另一个类 Odoo 10 中检索字段的值
- swift - 如何在 Swift 中使用 Alamofire 将参数作为正文发送到 PUT 方法
- r - 将因子列表向量拆分为数据框,每个因子级别都有列
- python - 使用 python docx 查找文档的长度
- c# - 将对象标记为已更改