这是开发中非常常见的使用场景。
首先,我们需要知道要获取的json是什么样的,有两种方式得知:
第一,查询API文档:
一般在网站API文档中会介绍,如下:
第二种,通过使用crul -H
获取:
这种方法需要使用到终端,上图也介绍了这个方式,如下:
$ curl -H "Accept: application/json" https://icanhazdadjoke.com/
{
"id": "R7UfaahVfFd",
"joke": "My dog used to chase people on a bike a lot. It got so bad I had to take his bike away.",
"status": 200
}
在我们知晓获取的JSON的格式之后,我们开始敲代码,首先头文件需要添加import Combine
,完整头文件如下:
import SwiftUI
import Combine
然后,我们需要新建一个结构体来解读存放JSON格式的内容。以上面获取的为例,此JSON每条数据有三个元素组成:
id
:需要注意这里的id
是字符串类型。但是有的id
是UUID类型。joke:很显然这是字符串类型。status:整数类型。
然后我们写如下结构体(需要注意类型千万不能写错,不然会解码错误):
//如果获取的JSON文件中含有多条,我们也打算存放到一个数组中,这里需要加上Identifiable
struct Joke: Codable {
var id: String
var joke: String
var status: Int
}
然后我们用刚写好的Joke类型
创建一个变量来获取和存储解码后的数据,内容全是空或0(你也可以根据需要添加合适的占位词)。并且出于方便,我直接写到视图的结构体中。
需要注意的是,演示中每次只获取了一条数据,我们可以使用单独的一个变量存放,每次刷新。但是平时我们更常使用数组来存放,如果这里使用数组存放的话,赋值的时候记得使用append
而不是=
。如果获取的JSON本身就包含好多条数据,那么还是用=
。
@State private var jokes: Joke = Joke(id: "", joke: "", status: 0)
然后就是写一个函数来获取、解码和存储JSON数据了(由于需要使用上面我们新建的变量,所以要把这个函数和变量放在同一个struct
或者class
中),如下:
func getJoke() {
//设置需要获取的网址
let url = URL(string: "https://icanhazdadjoke.com/")!
//请求网址
var urlRequest = URLRequest(url:url)
//请求获取的类型是application/json(也就是JSON类型)
urlRequest.addValue("application/json",forHTTPHeaderField: "Accept")
//检查获取到的数据
URLSession.shared.dataTask(with: urlRequest) { data, response, error in
do {
//将数据赋值给jokeDate,并且判断数据不为空的话
if let jokeData = data {
//设置解码器为JSONDecoder()
let decoder = JSONDecoder()
//按照我们之前创建的Joke结构体的数据结构解码获取到的数据(如果我们打算放到数组中,给这里的Joke加个中括号)
let decodedData = try decoder.decode(Joke.self, from: jokeData)
//为了防止数据过多,加载时间过长,这里使用异步加载
DispatchQueue.main.async {
//将解码后的数据赋值给之前准备好的空变量
self.jokes = decodedData
}
} else {
//如果数据是空的,在控制台输出下面的文本
print("No data")
}
} catch {
print(error)
}
}.resume()
}
下面列出完整代码:
import SwiftUI
import Combine
struct Joke: Codable {
var id: String
var joke: String
var status: Int
}
struct ContentView: View {
//来获取和存储解码后的数据的Joke数据类型的变量
@State private var jokes: Joke = Joke(id: "", joke: "", status: 0)
var body: some View {
VStack {
Button("获取") {
getJoke()
}
VStack(alignment: .leading) {
Text(jokes.joke)
}
.onAppear(perform: {
//界面出现的时候加载数据
getJoke()
})
}
}
func getJoke() {
//设置需要获取的网址
let url = URL(string: "https://icanhazdadjoke.com/")!
//请求网址
var urlRequest = URLRequest(url:url)
//请求获取的类型是application/json(也就是JSON类型)
urlRequest.addValue("application/json",forHTTPHeaderField: "Accept")
//检查获取到的数据
URLSession.shared.dataTask(with: urlRequest) { data, response, error in
do {
//将数据赋值给jokeDate,并且判断数据不为空的话
if let jokeData = data {
//设置解码器为JSONDecoder()
let decoder = JSONDecoder()
//按照我们之前创建的Joke结构体的数据结构解码获取到的数据(如果我们打算放到数组中,给这里的Joke加个中括号)
let decodedData = try decoder.decode(Joke.self, from: jokeData)
//为了防止数据过多,加载时间过长,这里使用异步加载
DispatchQueue.main.async {
//将解码后的数据赋值给之前准备好的空变量
self.jokes = decodedData
}
} else {
//如果数据是空的,在控制台输出下面的文本
print("No data")
}
} catch {
print(error)
}
}.resume()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
这里是为了方便演示,所以写在一起了。一般情况下,我们需要新建一个swift
文件来存放struct、请求获取和解码部分的代码。
希望能帮到有需要的人~
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)