【问题标题】:Swiift - Decoding json data from serverSwift - 从服务器解码 json 数据
【发布时间】:2021-07-26 20:31:05
【问题描述】:

我正在做一个项目,我必须显示来自网络调用的数据。问题是我无法解码从网络调用收到的数据并将其存储到 structs 变量中以用于其他调用。截止日期快到了,我不确定为什么我的代码不起作用。这是我收到的 json

{"result":{"login":{"isAuthorized":true,"isEmpty":false,"userName":{"isEmpty":false,"name":{"firstName":"Jason","lastName":"Test","displayName":"Test, Jason","isEmpty":false,"fullName":"Jason Test"},"canDelete":false,"id":5793,"canModify":false},"username":"test@testable.com"},"parameters":{"isEmpty":false,"keep_logged_in_indicator":false,"username":"test@testable.com"}},"isAuthorized":true,"version":{"major":"2021","minor":"004","fix":"04","display":"2021.004.04","isEmpty":false},"isSystemDown":false,"timestamp":"2021-07-26T20:21:43Z","isSuccess":true}

这是我在项目中制作的不同结构

struct ApiResponse: Decodable {
    let results: Results?
    let isAuthorized: Bool?
    let version: Version?
    let isSystemDown: Bool?
    let errors: [serverError]?
    let timestamp: Date?
    let isSuccess: Bool?
    
}

// MARK: - Result
struct Results: Decodable {
    let login: Login
    let parameters: Parameters?
}

// MARK: - Login
struct Login: Decodable {
    let isAuthorized, isEmpty: Bool?
    let userName: UserName
    let username: String?
}

// MARK: - UserName
struct UserName: Decodable {
    let isEmpty: Bool?
    let name: Name
    let canDelete: Bool?
    let id: Int
    let canModify: Bool?
}

// MARK: - Name
struct Name: Decodable {
    let firstName, lastName, displayName: String
    let isEmpty: Bool?
    let fullName: String
}

// MARK: - Parameters
struct Parameters: Decodable {
    let isEmpty, keepLoggedInIndicator: Bool?
    let username: String?

    enum CodingKeys: String, CodingKey {
        case isEmpty
        case keepLoggedInIndicator
        case username
    }
}

// MARK: - Version
struct Version: Decodable {
    let major, minor, fix, display: String?
    let isEmpty: Bool?
}

// Mark: - Error
struct serverError: Decodable {
    let password: String?
}

我用来解码 json 数据的代码是这样的

private func handleResponse<T: Decodable>(result: Result<Data, Error>?, completion: (Result<T, Error>) -> Void) {
        guard let result = result else {
            completion(.failure(AppError.unknownError))
            return
        }
        
        switch result {
        
            case .success(let data):
                
                do {
                    let json = try JSONSerialization.jsonObject(with: data, options: [])
                    print("Server JsonObject response: \(json)")
                    
                    } catch {
                        completion(.failure(error))
                    }
                
                
                let decoder = JSONDecoder()
                // decodes the Server response
                guard let response = try? decoder.decode(ApiResponse.self, from: data) else {
                    print("Something happen here")
                    completion(.failure(AppError.errorDecoding))
                    return
                }
                
                // Returns if an error occurs
                if let error = response.errors {
                    completion(.failure(AppError.serverError(error)))
                    return
                }
                // Decodes the data received from server
                if let decodedData = response.results {
                    completion(.success(decodedData as! T))
                } else {
                    completion(.failure(AppError.errorDecoding))
                }
                
            case .failure(let error):
                completion(.failure(error))
        }
    }

如果有人能帮助我理解为什么我的代码无法正常工作,那将不胜感激。

【问题讨论】:

  • 如果您在问题中包含您看到的错误,将更容易给您答复!
  • 仔细阅读 JSON。第一个键已经与结构不匹配。如果您不忽略解码错误并且不随意将所有内容声明为可选,那么您可以帮助自己。
  • 在解码时使用do/try/catchprint(error)catch 中,而不是try?。那么你至少可以得到一个有意义的错误。
  • “为什么我的代码不起作用” 它怎么不起作用?
  • @idz 我收到的错误来自一个自定义错误结构,我基本上告诉我它无法解码。更清楚地说,我的问题是如何正确解码收到的 json 数据。我在 swift 或应用程序开发以及使用 json 数据方面几乎没有经验

标签: swift generics


【解决方案1】:

你的结构是错误的。试试这个?

struct YourAPIData {
 struct Root: Codable {
    struct Result: Codable {
        struct Login: Codable {
            let isAuthorized: Bool
            let isEmpty: Bool
            struct UserName: Codable {
                let isEmpty: Bool
                struct Name: Codable {
                    let firstName: String
                    let lastName: String
                    let displayName: String
                    let isEmpty: Bool
                    let fullName: String
                }
                let name: Name
                let canDelete: Bool
                let id: Int
                let canModify: Bool
            }
            let userName: UserName
            let username: String
        }
        let login: Login
        struct Parameters: Codable {
            let isEmpty: Bool
            let keepLoggedInIndicator: Bool
            let username: String
            private enum CodingKeys: String, CodingKey {
                case isEmpty
                case keepLoggedInIndicator = "keep_logged_in_indicator"
                case username
            }
        }
        let parameters: Parameters
    }
    let result: Result
    let isAuthorized: Bool
    struct Version: Codable {
        let major: String
        let minor: String
        let fix: String
        let display: Date
        let isEmpty: Bool
    }
    let version: Version
    let isSystemDown: Bool
    let timestamp: String
    let isSuccess: Bool
 }
}

并尝试使用

 do {
      let APIData = try JSONDecoder().decode(YourAPIData.Root.self, from: jsonData)
} catch let jsonErr { print("Error: ", jsonErr) }
               

如果你想显示你的 json(我想是为了测试?)

if let data = jsonData, let body = String(data: jsonData, encoding: .utf8) {
      print(body)
    }
  } else {
    print(error ?? "Unknown error")
  }

【讨论】:

  • SwiftyJSON 根本不需要。
  • @vadian 哦,是的,我忘了。谢谢
  • @Zyfe3r 我收到了这个 - 错误:typeMismatch(Swift.Double, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "version", intValue: nil), CodingKeys(stringValue: "display ", intValue: nil)], debugDescription: "预期解码 Double 但找到了一个字符串/数据。",底层错误: nil))
  • @KwabenaDarkwa 编码是由您发布的 json 制成的。该错误准确地指定了您面临的问题。可编码已将Double 设置为“显示”,但数据为字符串格式。所以把它从double改成string?阅读错误。
  • @Zyfe3r 谢谢
猜你喜欢
  • 1970-01-01
  • 2023-03-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-04
  • 2021-12-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多