我有一个API,有时会以Int形式返回JSON中的特定键,而有时它会以String形式返回相同的键,我通过创建一个枚举IntOrString来解决此问题。现在的问题是,当我调用API更新这些特定键的标签时,类型是错误的。
然后我得到错误无法将Double类型转换为DoubleOrString类型
enum DoubleOrString: Codable {
case double(Double)
case string(String)
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
do {
self = try .double(container.decode(Double.self))
} catch DecodingError.typeMismatch {
do {
self = try .string(container.decode(String.self))
} catch DecodingError.typeMismatch {
throw DecodingError.typeMismatch(
DoubleOrString.self,
DecodingError.Context(
codingPath: decoder.codingPath,
debugDescription: "Encoded payload conflicts with expected type, (Double or String)"
)
)
}
}
}
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case .double(let double):
try container.encode(double)
case .string(let string):
try container.encode(string)
}
}
}
Run Code Online (Sandbox Code Playgroud)
降低这是我更新标签的地方
self.ageLabel.text = "\(pData.info.detailedInfo?.ageNumber ?? 0.0)"
Run Code Online (Sandbox Code Playgroud)
首先,我认为你应该决定是否真的想在DoubleOrString整个计划中保留这一点。您需要跟踪区别吗?或者你可以修改你的解码器以使其始终成为双精度吗?您的内部数据模型不必重新创建 JSON 中的每个错误。
如果您确实想维护枚举,那么我认为您正在寻找的是以下内容:
extension DoubleOrString {
var doubleValue: Double? {
switch self {
case .double(let double): return double
case .string(let string): return Double(string)
}
}
}
self.ageLabel.text = "\(pData.info.detailedInfo?.ageNumber.doubleValue ?? 0.0)"
Run Code Online (Sandbox Code Playgroud)
(当然,这里的首选解决方案是更正 JSON,以便它返回一致的类型。我认识到这并不总是可用的选项。)
如果您想消除 DoubleOrString(这通常是个好主意),请在结构中向上移动一个级别,并以age这种方式解码:
guard let age = try
(try? container.decode(Double.self, forKey: .age)) ??
Double(container.decode(String.self, forKey: .age))
else {
throw DecodingError.typeMismatch(Double.self,
DecodingError.Context(
codingPath: decoder.codingPath,
debugDescription: "Encoded payload conflicts with expected type, (Double or String)"))
}
self.age = age
Run Code Online (Sandbox Code Playgroud)
它尝试将其解码为双精度值,如果失败,它会尝试转换字符串值。如果密钥丢失,这仍然有助于抛出正确的错误,而不需要一堆 do/catch 块。
如果你有很多这样的东西,你可以这样总结:
struct JSONDouble: Codable {
let value: Double
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
guard let value = try
(try? container.decode(Double.self)) ??
Double(container.decode(String.self))
else {
throw DecodingError.typeMismatch(Double.self,
DecodingError.Context(
codingPath: decoder.codingPath,
debugDescription: "Encoded payload conflicts with expected type, (Double or String)"))
}
self.value = value
}
}
Run Code Online (Sandbox Code Playgroud)
那么你的解码逻辑就是:
self.age = try container.decode(JSONDouble.self, forKey: .age).value
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
87 次 |
| 最近记录: |