如何使用 decodable 正确解码此 json 字符串?
How do I properly decode this json string using decodable?
我有以下 json 字符串:
{"weight":[{"bmi":24.75,"date":"2020-01-20","logId":1000,"source":"API","time":"23:59:59","weight":200}]}
我想将其转换为 Swift 对象以便访问不同的值。这是我想要做的,我有这些结构设置:
struct FitbitResponseModel: Decodable {
let weight: [FitbitResponseData]
}
struct FitbitResponseData: Decodable {
let bmi: Int
let date: String
let logId: Int
let source: String
let time: String
let weight: Int
}
然后我用这个方法来解码 json 字符串:
func parseJSON(data: Data) -> FitbitResponseModel? {
var returnValue: FitbitResponseModel?
do {
returnValue = try JSONDecoder().decode(FitbitResponseModel.self, from: data)
} catch {
print("Error took place: \(error.localizedDescription).")
}
return returnValue
}
然而,当我尝试 运行 时,我得到了无法读取数据的错误,因为它的格式不正确。我究竟做错了什么?感谢任何帮助。
提前致谢!
与您的 API 开发人员交谈。 000
不是 json 的有效数字表示法。它必须是 0 或 0.0。您可以在 https://jsonlint.com 处检查 json 。如果你真的需要解决这个问题,我建议在解析数据之前用 0,
替换 000,
上的字符串。
Json 无效,因为您 json 中的 logId 值无效。
{
"weight": [{
"bmi": 24.75,
"date": "2020-01-20",
"logId": 100,
"source": "API",
"time": "23:59:59",
"weight": 200
}]
}
这个自动生成的一致性的一个非常巧妙的特性是,如果你在你的类型中定义一个符合 CodingKey 协议的枚举 "CodingKeys"(或使用具有此名称的类型别名)– Swift 将自动使用此作为键类型。因此,这使您可以轻松自定义您的属性 encoded/decoded 的键。
struct Base: Codable {
let weight : [Weight]?
enum CodingKeys: String, CodingKey {
case weight = "weight"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
weight = try values.decodeIfPresent([Weight].self, forKey: .weight)
}
}
struct Weight : Codable {
let bmi : Double?
let date : String?
let logId : Int?
let source : String?
let time : String?
let weight : Int?
enum CodingKeys: String, CodingKey {
case bmi = "bmi"
case date = "date"
case logId = "logId"
case source = "source"
case time = "time"
case weight = "weight"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
bmi = try values.decodeIfPresent(Double.self, forKey: .bmi)
date = try values.decodeIfPresent(String.self, forKey: .date)
logId = try values.decodeIfPresent(Int.self, forKey: .logId)
source = try values.decodeIfPresent(String.self, forKey: .source)
time = try values.decodeIfPresent(String.self, forKey: .time)
weight = try values.decodeIfPresent(Int.self, forKey: .weight)
}
}
希望对您有所帮助!
或者您可以使用 SwiftyJSON 库:https://github.com/SwiftyJSON/SwiftyJSON
改变
let bmi: Int
到
let bmi: Double
因为如果任何变量类型与 JSON 响应不匹配,它的值在您的响应中会出现 24.75 整个模型不会映射到 Codable 协议(Encodable 和 Decodable)
我有以下 json 字符串:
{"weight":[{"bmi":24.75,"date":"2020-01-20","logId":1000,"source":"API","time":"23:59:59","weight":200}]}
我想将其转换为 Swift 对象以便访问不同的值。这是我想要做的,我有这些结构设置:
struct FitbitResponseModel: Decodable {
let weight: [FitbitResponseData]
}
struct FitbitResponseData: Decodable {
let bmi: Int
let date: String
let logId: Int
let source: String
let time: String
let weight: Int
}
然后我用这个方法来解码 json 字符串:
func parseJSON(data: Data) -> FitbitResponseModel? {
var returnValue: FitbitResponseModel?
do {
returnValue = try JSONDecoder().decode(FitbitResponseModel.self, from: data)
} catch {
print("Error took place: \(error.localizedDescription).")
}
return returnValue
}
然而,当我尝试 运行 时,我得到了无法读取数据的错误,因为它的格式不正确。我究竟做错了什么?感谢任何帮助。
提前致谢!
与您的 API 开发人员交谈。 000
不是 json 的有效数字表示法。它必须是 0 或 0.0。您可以在 https://jsonlint.com 处检查 json 。如果你真的需要解决这个问题,我建议在解析数据之前用 0,
替换 000,
上的字符串。
Json 无效,因为您 json 中的 logId 值无效。
{
"weight": [{
"bmi": 24.75,
"date": "2020-01-20",
"logId": 100,
"source": "API",
"time": "23:59:59",
"weight": 200
}]
}
这个自动生成的一致性的一个非常巧妙的特性是,如果你在你的类型中定义一个符合 CodingKey 协议的枚举 "CodingKeys"(或使用具有此名称的类型别名)– Swift 将自动使用此作为键类型。因此,这使您可以轻松自定义您的属性 encoded/decoded 的键。
struct Base: Codable {
let weight : [Weight]?
enum CodingKeys: String, CodingKey {
case weight = "weight"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
weight = try values.decodeIfPresent([Weight].self, forKey: .weight)
}
}
struct Weight : Codable {
let bmi : Double?
let date : String?
let logId : Int?
let source : String?
let time : String?
let weight : Int?
enum CodingKeys: String, CodingKey {
case bmi = "bmi"
case date = "date"
case logId = "logId"
case source = "source"
case time = "time"
case weight = "weight"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
bmi = try values.decodeIfPresent(Double.self, forKey: .bmi)
date = try values.decodeIfPresent(String.self, forKey: .date)
logId = try values.decodeIfPresent(Int.self, forKey: .logId)
source = try values.decodeIfPresent(String.self, forKey: .source)
time = try values.decodeIfPresent(String.self, forKey: .time)
weight = try values.decodeIfPresent(Int.self, forKey: .weight)
}
}
希望对您有所帮助!
或者您可以使用 SwiftyJSON 库:https://github.com/SwiftyJSON/SwiftyJSON
改变
let bmi: Int
到
let bmi: Double
因为如果任何变量类型与 JSON 响应不匹配,它的值在您的响应中会出现 24.75 整个模型不会映射到 Codable 协议(Encodable 和 Decodable)