如何调用http接口获取json数据及GET/POST方式调用http接口
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何调用http接口获取json数据及GET/POST方式调用http接口相关的知识,希望对你有一定的参考价值。
参考技术A HTTP接口返回的JSON数据,其实就是HTTP请求后返回的HTTP主体那一部分。HTTP协议规定,HTTP头部和HTTP主体之间是以一个空行分割的。因为HTTP每一行(每一行是指一个头部字段)是以\r\n结束的,一个空行的\r\n,再加上最后一行的结束符\r\n,一起是\r\n\r\n,也就是说,当检测到\r\n\r\n四个字符时,下一个字符开始就是HTTP body的内容了。把HTTP响应主体保存下来就是JSON数据了。本回答被提问者采纳
如何在 Swift 5 中进行具有大 JSON 响应的 GET API 调用?
【中文标题】如何在 Swift 5 中进行具有大 JSON 响应的 GET API 调用?【英文标题】:How to make GET API calls that has large JSON response in Swift 5? 【发布时间】:2020-07-13 01:15:03 【问题描述】:我正在尝试从disease.sh 获取所有国家及其州的 Covid 19 数据。
我之前使用此方法从不同的 API 获取 json 数据。与此相比,这些情况下的响应时间更短。
我已经发布了以下代码:
// Webservice.swift
import Foundation
class Webservice
let countriesURL: String = "https://disease.sh/v3/covid-19/jhucsse"
func getAllCountries(completion: @escaping ([Country]?) ->())
guard let url = URL(string: countriesURL) else
completion(nil)
return
let request = URLRequest(url: url)
URLSession.shared.dataTask(with: request) data, response, error in
guard let data = data, error == nil else
print("No data in response: \(error?.localizedDescription ?? "Unknown error").")
DispatchQueue.main.async
completion(nil)
return
let countries = try? JSONDecoder().decode([Country].self, from: data)
DispatchQueue.main.async
countries == nil ? completion(nil) : completion(countries)
.resume()
由于我使用的是 MVVM 设计,这里是我的模型、视图模型和视图。
// Model
// Country.swift
import Foundation
struct Country: Decodable
var country: String
var updatedAt: String
var stats: Stats
var coordinates: Coordinates
var province: String
struct Stats: Decodable
var confirmed: Int
var deaths: Int
var recovered: Int
struct Coordinates: Decodable
var latitude: String
var longitude: String
// ViewModel
// CountryListViewModel.swift
import Foundation
class CountryListViewModel: ObservableObject
@Published var countries = [CountryViewModel]()
init()
fetchCountries()
func fetchCountries()
Webservice().getAllCountries() countries in
if let countries = countries
self.countries = countries.map(CountryViewModel.init)
class CountryViewModel
var country: Country
init(country: Country)
self.country = country
let id = UUID()
var name: String
return self.country.country
var updatedAt: String
return self.country.updatedAt
var stats: Stats
return self.country.stats
var coordinates: Coordinates
return self.country.coordinates
var province: String
return self.country.province
// View
// ContentView.swift
import SwiftUI
struct ContentView: View
@ObservedObject private var countryListVM = CountryListViewModel()
var body: some View
List( self.countryListVM.countries, id:\.id) country in
Text(country.name)
struct ContentView_Previews: PreviewProvider
static var previews: some View
ContentView()
我的问题是当我调用 Webservice.getAllCountries() 时它返回 nil。任何人都可以看看代码并告诉我有什么问题吗?谢谢!
PS:我创建了一个具有较少对象 (20-30) 的模拟 json,并在这种情况下调用了 Webservice.getAllCountries(),它返回并映射了值。它不适用于更大的 JSON 响应。 救命!!
【问题讨论】:
您从 Web 服务得到什么响应?你有错误吗?错误是什么? 那是因为当国家 == 0 和你的完成块时你只是返回 nil 吗? 该文档说“数据任务使用 NSData 对象发送和接收数据。数据任务用于向服务器发送简短的、通常是交互式的请求”关于URLSession
。
那个 URL 似乎没有返回一个特别大的数据集。不要使用try ?
- 这会丢弃解码错误。使用do/try/catch
并至少打印任何产生的错误
感谢您也提供了一个很好的问题;所有的代码都在那里,你解释了你尝试了什么以及发生了什么。
【参考方案1】:
你应该避免使用try ?
,除非在你真的不关心失败的情况下。 do/try/catch
是一种更好的方法,因为它会告诉您为什么某些事情失败了。
将代码更改为
do
let countries = try JSONDecoder().decode([Country].self, from: data)
DispatchQueue.main.async
completion(countries)
catch
print(error)
completion(nil)
在控制台上给我们一个错误 -
Swift.DecodingError.Context(codingPath: [_JSONKey(stringValue: "Index 509", intValue: 509), CodingKeys(stringValue: "province", intValue: nil)], debugDescription: "预期的字符串值,但发现为空.",基础错误:无))
这是有道理的,因为并非所有国家都有省份。要解决此问题,请在您的数据模型中将 province
设为可选
struct Country: Decodable
var country: String
var updatedAt: String
var stats: Stats
var coordinates: Coordinates
var province: String?
【讨论】:
谢谢@Paulw11,我刚刚注意到我没有处理来自响应的空值。我这边犯了这样的错误。再次感谢,干杯伙伴!以上是关于如何调用http接口获取json数据及GET/POST方式调用http接口的主要内容,如果未能解决你的问题,请参考以下文章
MicroPython ESP32Http Get方法获取网络时间+OLED显示