当我使用 Postman 访问我的配置 API 时,我得到了以下 json 响应。在此响应中,两个 apiVersion 键是数字而不是字符串。
{
"data": {
"availability": {
"auth": true,
"ab": true,
"cd": true
},
"helloWorldConfiguration": {
"apiKey": "abcefg",
"rootUrl": "https://foo",
"apiVersion": 3
},
"fooBarConfiguration": {
"baseUrl": "https://foo",
"apiVersion": 1,
"privateApiPath": "",
"publicApiPath": "dev",
"tokenPath": ""
}
},
"errors": []
}
当我尝试对其进行解码时,它会因typeMismatch错误而失败。当我输出响应的内容时,我看到以下内容对我来说很好。
data = {
availability = {
auth = 1;
ab = 1;
cd = 1;
};
helloWorldConfiguration = {
apiVersion = 1;
baseUrl = "https://foo";
privateApiPath = "";
publicApiPath = dev;
tokenPath = "";
};
fooBarConfiguration = {
apiKey = abcefg;
apiVersion = 3;
rootUrl = "https://foo";
};
};
errors = (
);
给我的错误表明它data.helloWorldConfiguration.apiVersion的类型是字符串而不是 int。从我从 Postman 得到的原始 HTTP 响应中,我们可以看出并非如此。
typeMismatch(Swift.Int, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "data", intValue: nil), CodingKeys(stringValue: "helloWorldConfiguration", intValue: nil), CodingKeys(stringValue: "apiVersion", intValue :nil)],debugDescription:“预期解码 Int,但找到了一个字符串/数据。”,基础错误:nil)) 21:17:40 错误无法将响应数据解码为模型表示。
我的模型将这些属性表示为整数,因此它似乎接收到响应并将这些数字视为字符串,但事实并非如此。
public struct ServerConfiguration: Decodable {
let availability: AvailabilityConfiguration
let helloWorldConfiguration: HelloWorldConfiguration
let fooBarConfiguration: FooBarConfiguration
init(availability: AvailabilityConfiguration, helloWorldConfiguration: HelloWorldConfiguration, fooBarConfiguration: FloatSinkConfiguration) {
self.availability = availability
self.helloWorldConfiguration = helloWorldConfiguration
self.fooBarConfiguration = fooBarConfiguration
}
}
public struct FooBarConfiguration: Decodable {
let baseUrl: String
let apiVersion: Int
let privateApiPath: String
let publicApiPath: String
let tokenPath: String
init(baseUrl: String, apiVersion: Int, privateApiPath: String, publicApiPath: String, tokenPath: String) {
self.baseUrl = baseUrl
self.apiVersion = apiVersion
self.privateApiPath = privateApiPath
self.publicApiPath = publicApiPath
self.tokenPath = tokenPath
}
}
public struct AvailabilityConfiguration: Decodable {
let auth: Bool
let ab: Bool
let cd: Bool
init(auth: Bool, ab: Bool, cd: Bool) {
self.auth = auth
self.ab = ab
self.cd = cd
}
}
public struct HelloWorldConfiguration: Codable {
let apiKey: String
let rootUrl: String
let apiVersion: Int
init(apiKey: String, rootUrl: String, apiVersion: Int) {
self.apiKey = apiKey
self.rootUrl = rootUrl
self.apiVersion = apiVersion
}
}
如您所见,我的apiVersion成员都是整数类型以及 json 响应。我在这里做错了什么?我假设发生的事情是 Swift 正在考虑 json 字符串中的数字,而不管它们在 json 中的实际表示方式。是这样吗?
编辑以显示 Alamofire 响应数据的 utf8 字符串
21:44:06 INFO GET: https:foo/configuration
{
"data" : {
"availability" : {
"auth" : true,
"ab" : true,
"cb" : true
},
"helloWorldConfiguration" : {
"apiKey" : "abcd",
"rootUrl" : "https://foo",
"apiVersion" : "3"
},
"fooBarConfiguration" : {
"baseUrl" : "https://foo",
"apiVersion" : "1",
"privateApiPath" : "",
"publicApiPath" : "dev",
"tokenPath" : "auth/token"
}
},
"errors" : []
}
看起来尽管 API 正确地apiVersion以数字形式返回,但 Swift 正在将其转换为字符串。我解码不正确吗?
func getRoute<TResponseData: Decodable>(route:String, completion: @escaping (TResponseData) -> Void) throws {
let headers = try! self.getHeaders(contentType: ContentType.json)
let completeUrl: String = self.getUrl(route: route, requestUrl: nil)
logger.info("GET: \(completeUrl)")
Alamofire.request(
completeUrl,
method: .get,
parameters: nil,
encoding: JSONEncoding.default,
headers: headers)
.validate()
.responseJSON { (response) -> Void in
self.logger.info("GET Response: \(String(describing:response.response?.statusCode))")
switch response.result {
case .success(_):
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .custom(Date.toFooBarDate)
do {
let result = try decoder.decode(TResponseData.self, from: response.data!)
completion(result)
} catch DecodingError.dataCorrupted(let error) {
self.logger.error(error.underlyingError!)
return
} catch {
print(response.result.value!)
print(error)
self.logger.error("Unable to decode the response data into a model representation.")
return
}
}
}