[英]Using codable protocol to parse JSON
無法讀取數據,因為它的格式不正確。 嘗試解析下面給出的 JSON。 將數據對象也包含在結構中時引發錯誤
我的 JSON
{
"status": 200,
"message": "Logged in successfully.",
"error_message": [],
"data": {
"id": "179",
"home_address": "Optiquall Pune Maharashtra India",
"user_login": "mukti.thakor@optiquall.com",
"first_name": "mukti",
"last_name": "thakor",
"email": "mukti.thakor@optiquall.com",
"phone_number": "",
"timezone": "Asia/Calcutta",
"is_google_authenticated": "1",
"is_facebook_authenticated": "1",
"image_url": "",
"active_trip_id": "0",
"journey_type": "",
"trip_identifier": "",
"trip_author": "",
"token_info": {
"access_token": "e692f28b8ffe16e683540e7b2d42286a47cbe7fb",
"expires_in": "3600",
"token_type": "Bearer",
"scope": null,
"refresh_token": "8512b001e35eb69c7d3b45e20138bf91b210bafb"
}
},
"notification_count": 0
}
我的代碼
let decoder = JSONDecoder()
//decoder.keyDecodingStrategy = .convertFromSnakeCase
do{
let succeResponse = try decoder.decode(successResponse.self, from: data!)
print(succeResponse.data)
} catch let error as Error{
print(error.localizedDescription)
}
struct SuccessResponse: Codable {
var status:Int?
var message:String?
var errorMessage:[Int]? = []
//var developerMessage:String?
var notificationCount:Int?
var data:data
private enum CodingKeys : String, CodingKey {
case status = "status", message = "message", notificationCount = "notification_count", errorMessage = "error_message", data = "data"
}
}
struct Data: Codable {
var id:Int?
var homeAddress:String?
var userLogin:String?
var firstName:String?
var lastName:String?
var email:String?
var phoneNumber:String?
var timezone:String?
var isGoogleAuthenticated:String?
var isFacebookAuthenticated:String?
var imageUrl:String?
var activeTripId:String?
var journeyType:String?
var tripIdentifier:String?
var tripAuthor:String?
var tokenInfo:tokenInfo
private enum CodingKeys : String, CodingKey {
case id = "id", homeAddress = "home_address", userLogin = "user_login", firstName = "first_name", lastName = "last_name", email = "email", phoneNumber = "phone_number", timezone = "timezone", isGoogleAuthenticated = "is_google_authenticated",isFacebookAuthenticated = "is_facebook_authenticated", imageUrl = "image_url", activeTripId = "active_trip_id", journeyType = "journey_type", tripIdentifier = "trip_identifier" , tripAuthor = "trip_author", tokenInfo = "token_info"
}
}
struct TokenInfo: Codable {
var accessToken:String?
var expiresIn:String?
var tokenType:String?
var scope:Bool?
var refreshToken:String?
private enum CodingKeys : String, CodingKey {
case accessToken = "access_token", expiresIn = "expires_in", tokenType = "token_type", scope = "scope", refreshToken = "refresh_token"
}
}
代替
var id:Int?
和
var id:String?
首先,正如評論中提到的,在DecodingError
捕獲塊中永遠不要print(error.localizedDescription)
。 始終print(error)
以獲取此全面的錯誤消息:
typeMismatch(Swift.Int, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "data", intValue: nil), CodingKeys(stringValue: "id", intValue: nil)], debugDescription: "預期解碼 Int 但找到了一個字符串/數據。”,underlyingError: nil))
它告訴您結構data
中的鍵id
值( [CodingKeys(stringValue: "data", intValue: nil), CodingKeys(stringValue: "id", intValue: nil)] )是一個字符串(找到一個字符串/ data ) 而不是預期解碼Int 。
因此,按照 Sh_Khan 的回答中的建議,將id
聲明為String
。
這是一個能夠解碼成功和失敗案例的解決方案。
根據status
的值,根對象被解碼為具有關聯值的枚舉。
其他變化:
Response
和UserData
scope
)都被聲明為非可選的。 如果您收到錯誤消息,請僅將受影響的類型更改為可選項。let
)。convertFromSnakeCase
策略結構:
enum Response : Decodable {
case success(Int, Int, String, UserData)
case failure(Int, Int, String, [String:String])
private enum CodingKeys : String, CodingKey {
case status = "status", message = "message", notificationCount = "notificationCount", errorMessage = "errorMessage", data = "data"
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let status = try container.decode(Int.self, forKey: .status)
let notificationCount = try container.decode(Int.self, forKey: .notificationCount)
let message = try container.decode(String.self, forKey: .message)
if status == 200 {
let userData = try container.decode(UserData.self, forKey: .data)
self = .success(status, notificationCount, message, userData)
} else {
let errorMessage = try container.decode([String:String].self, forKey: .errorMessage)
self = .failure(status, notificationCount, message, errorMessage)
}
}
}
struct UserData : Decodable {
let id, homeAddress, userLogin, firstName, lastName, email, phoneNumber, timezone : String
let isGoogleAuthenticated, isFacebookAuthenticated, imageUrl, activeTripId, journeyType, tripIdentifier, tripAuthor : String
let tokenInfo : TokenInfo
}
struct TokenInfo : Decodable {
let accessToken, expiresIn, tokenType, refreshToken : String
let scope : String?
}
用法:
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
do {
let response = try decoder.decode(Response.self, from: data!)
switch response {
case let .success(status, notificationCount, message, userData): print(status, notificationCount, message, userData)
case let .failure(status, notificationCount, message, errorMessage): print(status, notificationCount, message, errorMessage)
}
} catch {
print(error)
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.