如何调用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显示

调用接口,解析Json字符串并存入数据库

jQuery AJAX获取JSON数据

如何使用 this.$http.get() 从 url 获取 json 数据?

如何使用eolinker对http的接口测试

httpclient get请求返回的数据乱码?跪求大神帮帮我..下面是代码,就是一个调用接口返回天气预报json数据