问题描述
我应该解析header(wtf)内部的数据,而不是正文。 响应标头格式如下:
{
"InferResponse":
{
"modelName": "aixyolov2","modelVersion": "1","batchSize": 1,"output":
[
{
"name": "OUTPUT2","raw":
{
"dims": ["1"],"batchByteSize": "4"
}
},{
"name": "OUTPUT0","raw":
{
"dims": ["1","4"],"batchByteSize": "16"
}
},{
"name": "OUTPUT1","batchByteSize": "4"
}
}
]
},"Status":
{
"code": "SUCCESS","serverId": "inference:0","requestId": "12"
},"Content-Length": 320,"Content-Type": "application/octet-stream"
}
我制作了三个包含数据的结构
struct Raw: Decodable {
let dims: [String]?
let batchByteSize: String?
}
struct Output: Decodable {
let name: String?
let raw: Raw?
}
struct InferResponse: Decodable {
let modelName: String?
let modelVersion: String?
let batchSize: String?
let output: [Output]?
}
因此,我实现了APIManager类来发送帖子并解析http响应标头。 代码如下。
class APIManager {
static private let apiKey = "fill in key" // paste in Key(Token)
static private let apiUrl = "fill in url" // paste in URL
func postData(image: UIImage) {
let urlString = APIManager.apiUrl
let url = URL(string: urlString)
guard url != nil else {
print("URL nil")
return
}
// header
let token = "Bearer \(APIManager.apiKey)"
var urlRequest = URLRequest(url: url!,cachePolicy: .useProtocolCachePolicy,timeoutInterval: 1)
urlRequest.httpMethod = "POST"
urlRequest.setValue(token,forHTTPHeaderField: "Authorization")
urlRequest.setValue("batch_size: 1 input { name: \"input\" } output { name: \"Darknet\" cls { count: 1 } }",forHTTPHeaderField: "InferRequest") // fix this when we get actual value
// body
let imageData = image.pngData()
urlRequest.httpBody = imageData?.base64EncodedData()
// handle the request
let dataTask = URLSession.shared.dataTask(with: urlRequest) { (data,response,error) in
if (error == nil && response != nil) {
let httpResponse = response as? HTTPURLResponse
if let inferResponse = httpResponse?.allHeaderFields["InferResponse"] as? String {
let newData = inferResponse.data(using: .utf8)! // this is the part I'm having trouble with
do {
let parsedResponse = try JSONDecoder().decode(InferResponse.self,from: newData)
}
catch {
}
}
else {
print("failed to obtain 'InferResponse' field from response header")
}
}
}
}
}
但是,我对HTTP标头数据感到困惑。我的经理向我发送了一个二进制标头响应,她说这会有所帮助。那么,这是否意味着HTTP响应标头数据是二进制的?然后,我应该使用utf编码将其转换为字符串,然后将其解析为JSON吗?请给我一些有关如何改进此代码的建议。谢谢。
if let inferResponse = httpResponse?.allHeaderFields["InferResponse"] as? String {
let newData = inferResponse.data(using: .utf8)! // this is the part I'm having trouble with
do {
let parsedResponse = try JSONDecoder().decode(InferResponse.self,from: newData)
}
catch {
}
}
解决方法
您快到了。解码操作由于数据类型而引发错误:
typeMismatch(Swift.String,Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "batchSize",intValue: nil)],debugDescription: "Expected to decode String but found a number instead.",underlyingError: nil))
这表明您的InferResponse.batchSize
是Int
,而不是String
:
struct InferResponse: Decodable {
let modelName: String?
let modelVersion: String?
let batchSize: Int?
let output: [Output]?
}
以后,请确保处理您的错误(执行/捕获)(或至少将其打印出来)。这应该有助于调试。