应解码Int,但找到了一个数字



我在Swift 4.2中遇到了JSON解析问题。下面的代码显示了运行时错误。

我从服务器得到的Json数据如下。

{
code: 406,
message: "Email Address already Exist.",
status: 0
}

我正在使用Codable按照创建我的结构

struct Registration: Codable {
var code: Int
var status: Int
private enum CodinggKeys: String, CodingKey {
case code
case status
}
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
do {
self.code = Int(try container.decode(String.self, forKey: .code))!
} catch DecodingError.typeMismatch {
let value = try container.decode(Double.self, forKey: .code)
self.code = Int(value);
}
do {
self.status = try container.decode(Int.self, forKey: .status)
} catch DecodingError.typeMismatch {
let value = try container.decode(String.self, forKey: .status)
self.status = Int(value);
}
}
} 

但每次我在解析状态键时都会出错。

注意:我曾尝试在String、Int、Double、Decimal、NSInterger中解析状态,但都不起作用。每次我都会犯同样的错误。应解码UInt,但找到了一个数字。

错误消息非常具有误导性。当JSON包含布尔值,并且结构具有对应键的Int属性时,就会发生这种情况。

很可能您的JSON实际上是这样的:

{
"code": 406,
"message": "Email Address already Exist.",
"status": false
}

因此,您的结构应该是

struct Registration: Codable {
let code: Int
let status: Bool
}
if let registration = try? JSONDecoder().decode(Registration.self, from: data) {
print(registration.code) // 406
print(registration.status) // false
}

我认为我们可以使用它来解决这样的问题:

protocol DecodingHelper {
associatedtype Keys: CodingKey
static func getStringValue(_ container: KeyedDecodingContainer<Keys>, key: Keys) -> String
static func getIntValue(_ container: KeyedDecodingContainer<Keys>, key: Keys) -> Int
static func getBoolValue(_ container: KeyedDecodingContainer<Keys>, key: Keys) -> Bool
}
extension DecodingHelper {
static func getStringValue(_ container: KeyedDecodingContainer<Keys>, key: Keys) -> String {
var str: String = ""
if let obj = try? container.decode(String.self, forKey: key) {
str = obj
}
else if let obj = try? container.decode(Int.self, forKey: key){
str = String(obj)
}
return str
}
static func getIntValue(_ container: KeyedDecodingContainer<Keys>, key: Keys) -> Int {
var val: Int = 0
if let obj = try? container.decode(String.self, forKey: key),
let intVal = Int(obj){
val = intVal
}
else if let obj = try? container.decode(Int.self, forKey: key){
val = obj
}
return val
}
static func getBoolValue(_ container: KeyedDecodingContainer<Keys>, key: Keys) -> Bool {
var val: Bool = false
if let obj = try? container.decode(String.self, forKey: key),
let intVal = Int(obj){
(intVal != 0) ? (val = true) : (val = false)
}
else if let obj = try? container.decode(Int.self, forKey: key){
(obj != 0) ? (val = true) : (val = false)
}
else if let obj = try? container.decode(Bool.self, forKey: key){
val = obj
}
return val
}
}

struct VideoFeedback: Codable {
// MARK:- Variables -
var isFeedbackProvided:Bool = true
// MARK:- Initialisation -
private enum CodingKeys: String, DecodingHelper, CodingKey {
typealias Keys = CodingKeys
case isFeedbackProvided = "lastVideoFeedback"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
isFeedbackProvided = CodingKeys.getBoolValue(values, key: .isFeedbackProvided)
}
}

如果你有任何改进的建议,请告诉我。

对于这类问题,请检查并确保结构中给出的响应和响应类型相同。你的回答似乎不正确。状态可能为真或假

{
code: 406,
message: "Email Address already Exist.",
status: 0
}

如果状态为true,请将结构更改为

struct Registration: Codable {
var code: Int
var status: Bool
var message: String
}

如果状态为0,则将上述结构中的var status: Bool更改为var status: Int

如果结构的属性已经是Decodable,则不需要实现自己的解码初始值设定项。您也不需要@Gereon提到的自定义CodingKeys

对于以下JSON数据:

let data = """
{
"code": 406,
"message": "Email Address already Exist.",
"status": 0
}
""".data(using: .utf8)!

这很好:

struct Registration: Codable {
var code: Int
var status: Int
}
if let registration = try? JSONDecoder().decode(Registration.self, from: data) {
print(registration.code) // 406
print(registration.status) // 0
}

有关详细信息,请参阅Apple的"编码和解码自定义类型"。

相关内容

  • 没有找到相关文章

最新更新