当我用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
的类型为string而不是int。我们可以从邮递员那里得到的原始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中的实际表示方式如何。是这样吗?
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
}
}
}
答案 0 :(得分:0)
我在操场上检查了一下,看来一切正常。要找到真正的问题,我认为您需要提供获取json的真实网址,并可以使用alamofire进行检查
import Foundation
let json = """
{
"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": []
}
"""
let data = json.data(using: .utf8)
struct Response : Codable {
let data : Data?
let errors : [String]?
}
struct Availability : Codable {
let auth : Bool?
let ab : Bool?
let cd : Bool?
}
struct Data : Codable {
let availability : Availability?
let helloWorldConfiguration : HelloWorldConfiguration?
let fooBarConfiguration : FooBarConfiguration?
}
struct FooBarConfiguration : Codable {
let baseUrl : String?
let apiVersion : Int?
let privateApiPath : String?
let publicApiPath : String?
let tokenPath : String?
}
struct HelloWorldConfiguration : Codable {
let apiKey : String?
let rootUrl : String?
let apiVersion : Int?
}
let decoder = JSONDecoder()
let response = try decoder.decode(Response.self, from: data!)
print(response)
这是回应
响应(数据:可选(__lldb_expr_11.Data(可用性:可选(__lldb_expr_11.Availability(auth:可选(true),ab:可选(true),cd:可选(true)))),helloWorldConfiguration:可选(__lldb_expr_11。 HelloWorldConfiguration(apiKey:Optional(“ abcefg”),rootUrl:Optional(“ https://foo”),apiVersion:Optional(3))),fooBarConfiguration:Optional(__ lldb_expr_11.FooBarConfiguration(baseUrl:Optional(“ {{3}) }“),apiVersion:可选(1),privateApiPath:可选(”“),publicApiPath:可选(” dev“),tokenPath:可选(”“))))))),错误:可选([]))>