json - Swift5 在响应头(二进制)中解析 JSON
问题描述
我应该解析标题(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",
"raw":
{
"dims": ["1"],
"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
是 a Int
,而不是 a String
:
struct InferResponse: Decodable {
let modelName: String?
let modelVersion: String?
let batchSize: Int?
let output: [Output]?
}
将来,请确保从 do/catch 处理您的错误(或至少将它们打印出来)。这应该有助于调试。
推荐阅读
- android - 具有固定高度的 Recyclerview 不会在嵌套滚动视图中滚动
- python - 为什么 pd.to_numeric 不适用于大数字?
- python - 问号的 Python 正则表达式
- java - 是什么阻止了 Cloneable 成为像 StringBuilder 这样的可变对象?
- php - 日期时间比较在 MySQL 中返回错误结果
- angular - 无法在 catcherror Angular 6 中设置超时
- audio - 使用 UWP 监控实时音频并检测枪声/拍手声
- jmeter - 响应代码:503 响应消息:服务不可用
- sql-server - 操作数数据类型“text”对“max”运算符无效
- vb.net - 如何在 Outlook 加载项打开时启用选择新电子邮件?