如何处理这个JSON?



我有这个JSON来自服务器:

{
"models": [
{
"code": "RPX",
"name": "Tank",
"color": null,
"alias": [
"tank"
],
"plantCode": "FR",
"countryName": "France",
"plantAlias": null,
"plantGroup": "5",
"matrix": [
{
"size": "BIG",
"union": null
}
],
"imageURL": "https://example.com/tank.jpg"
}
]
}

从这个JSON我已经建立了这个模型:

import Foundation
// MARK: - Welcome
struct ModelDecode: Codable {
let models: [Model]?
}
// MARK: - Model
struct Model: Codable {
let code, name: String?
let color: JSONNull?
let alias: [String]?
let plantCode, countryName: String?
let plantAlias: JSONNull?
let plantGroup: String?
let matrix: [Matrix]?
let imageURL: String?
}
// MARK: - Matrix
struct Matrix: Codable {
let size: String?
let union: JSONNull?
}
// MARK: - Encode/decode helpers
class JSONNull: Codable, Hashable {
public static func == (lhs: JSONNull, rhs: JSONNull) -> Bool {
return true
}
public var hashValue: Int {
return 0
}
public func hash(into hasher: inout Hasher) {
// No-op
}
public init() {}
public required init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if !container.decodeNil() {
throw DecodingError.typeMismatch(JSONNull.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for JSONNull"))
}
}
public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try container.encodeNil()
}
}

然后我解码JSON:

final class ListOfTanks:NSObject, URLSessionDelegate {

private let session: URLSession = NetworkService.shared.getSession()
private let decoder = JSONDecoder()
private let encoder = JSONEncoder()

static let shared = ListOfTanks()

static func serverURL() -> URL? {
let getServerHost = "https://example.com/request"
let getServerPath = "/getTanks"

var components = URLComponents()
components.scheme = "https"
components.host = getServerHost
components.path = getServerPath
guard let url = components.url else { return nil }
return url
}


static func getRequest() -> URLRequest? {
guard let url = ListOfTanks.serverURL()
else { return nil }

var request: URLRequest = URLRequest(url: url)
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue("service", forHTTPHeaderField: "iPad")
request.httpMethod = "GET"
return request
}

func getStations(completion:callback<ModelDecode>?) {

guard let request = ListOfTanks.getRequest() else {
completion?(.failure("Failed to build request"))
return }

let session: URLSession = URLSession(configuration: URLSessionConfiguration.default,
delegate: self,
delegateQueue: OperationQueue())

let task = session.dataTask(with: request as URLRequest) { (data, response, error) -> Void in

guard let data = data else {
completion?(.failure("Error"))
return
}

do {
let result = try self.decoder.decode(ModelDecode.self, from: data)
completion?(.success(result))
} catch (let error) {
print(error)
completion?(.failure("Error Parsing Error (String(describing:error))"))
}

}
task.resume()

}

}

正确检索JSON,但解码的最后一个try失败:

typeMismatch(MyApp.JSONNull, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "models", intValue: nil), _JSONKey(stringValue: "Index 1", intValue: 1), CodingKeys(stringValue: "matrix", intValue: nil), _JSONKey(stringValue: "Index 1", intValue: 1), CodingKeys(stringValue: "union", intValue: nil)], debugDescription: "Wrong type for JSONNull", underlyingError: nil))
failure("Error Parsing Error typeMismatch(MyApp.JSONNull, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "models", intValue: nil), _JSONKey(stringValue: "Index 1", intValue: 1), CodingKeys(stringValue: "matrix", intValue: nil), _JSONKey(stringValue: "Index 1", intValue: 1), CodingKeys(stringValue: "union", intValue: nil)], debugDescription: "Wrong type for JSONNull", underlyingError: nil))")

我如何解决这个问题?

注意:我省略了一些代码,我认为是隐式的,一旦JSON被正确检索。如果您需要一些具体的代码,请询问。

您应该做的第一件事是摆脱JSONNull类型。这没有帮助。一旦JSON值与null不同,这种类型将无法解码。而一个总是保持null的属性似乎是没有意义的。

下一步是将JSONNull替换为它们的"real"可选的类型。这里有多种方法

  • 得到更好的样品。因为你似乎已经通过快速类型创建了这个结构。将更大的数据集粘贴到其中。这很有可能为您提供所需的类型。

  • 做一个假设。因为所有的属性似乎都是String类型所以应该是(有点)可以安全地假设丢失的是同一类型。将JSONNull替换为String?

  • 问/读。阅读文档或联系API的所有者/开发人员,询问有哪些类型以及哪一种可以获得null

最新更新