提问人:darencorp 提问时间:1/12/2022 更新时间:1/12/2022 访问量:1595
在 Swift 中从响应数据中解码 json 字符串到结构
Decode json string to struct from response data in Swift
问:
我有一个用 python 编写的测试服务器,它在单个路径上生成 json 输出:“/”
import json
from fastapi import FastAPI
from uvicorn import run
app = FastAPI()
@app.get('/')
def main():
return json.dumps([{
'name': 'ihor',
'age': 5
}])
if __name__ == '__main__':
run(app, host='0.0.0.0')
然后我在 SwiftUI 中拥有我的 iOS 客户端,并尝试从我的服务器获取一个 json 并将其解码为结构。
下面是 api 调用和解码的代码:
import SwiftUI
class Network: ObservableObject {
@Published var users: [User] = []
func getUsers() {
let url = URL(string: "http://localhost:8000")
let urlRequest = URLRequest(url: url!)
let dataTask = URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in
if let error = error {
print("Request error: ", error)
return
}
guard let response = response as? HTTPURLResponse else { return }
if response.statusCode == 200 {
guard let data = data else { return }
DispatchQueue.main.async {
do {
print(String(decoding: data, as: UTF8.self))
let decodedUsers = try JSONDecoder().decode([User].self, from: data)
self.users = decodedUsers
} catch let error {
print("Error decoding: ", error)
}
}
}
}
dataTask.resume()
}
}
struct User: Decodable {
var name: String
var age: Int
}
它是从简单的内容视图调用的
import SwiftUI
struct ContentView: View {
@EnvironmentObject var network: Network
var body: some View {
ScrollView {
Text("All users")
.font(.title).bold()
if network.users.count > 0 {
Text(network.users.first!.name)
}
}
.onAppear {
network.getUsers()
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView() .environmentObject(Network())
}
}
毕竟,它会产生下一个输出:
"[{\"name\": \"ihor\", \"age\": 5}]" Error decoding: typeMismatch(Swift.Array<Any>, Swift.DecodingError.Context(codingPath: [], debugDescription: "Expected to decode Array<Any> but found a string/data instead.", underlyingError: nil))
看起来 JSONDecoder 无法处理开头和结尾带有转义反斜杠和引号的输入。
一旦我删除了第一个和最后一个引号并转义的反斜杠,一切正常:
do {
let rawJsonString = String(decoding: data, as: UTF8.self)
let lowerIndex = rawJsonString.index(rawJsonString.startIndex, offsetBy: 1)
let upperIndex = rawJsonString.index(rawJsonString.endIndex, offsetBy: -1)
let jsonString = rawJsonString[lowerIndex..<upperIndex].replacingOccurrences(of: "\\", with: "")
print(jsonString)
let decodedUsers = try JSONDecoder().decode([User].self, from: jsonString.data(using:.utf8)!)
self.users = decodedUsers
} catch let error {
print("Error decoding: ", error)
}
但这是非常肮脏的解决方案,不适用于必须使用反斜杠转义的嵌套 json。
有没有一个简单的解决方案可以像这样解析JSON到结构?
答: 暂无答案
上一个:用科学记数法编写 JSON 浮点
评论
print("Data: \(data.map { String(format: "%02hhx", $0) }.joined())
print(String(decoding: data, as: UTF8.self))
let decoder = JSONDecoder(); let stringified = try decoder.decode(String.self, from: data); let users = try decoder.decode([User].self, from: Data(stringified.utf8))
json.dumps
String
Swift
Array
String
json.dumps