如何使用 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)