json - 如何在 SwiftUI 中访问嵌套的 JSON API 数据?
问题描述
我正在尝试在 SwiftUI 中构建一个公共交通应用程序。我收到了一个 API,我可以在其中搜索瑞典斯德哥尔摩的始发站和目的地站,以及我想旅行的日期和时间,然后获取旅行路线。
这是我正在使用的 JSON 文件的一部分(完整的文件在下面的评论中):
{
"Trip": [
{
"ServiceDays": [
{
"planningPeriodBegin": "2021-01-05",
"planningPeriodEnd": "2021-05-20",
"sDaysR": "m\u00e5n - fre",
"sDaysI": "utom 13., 14. maj",
"sDaysB": "33E7CF9F3E7CF9F3E7CF9C1E7CF9F3E70F"
}
],
"LegList": {
"Leg": [
{
"Origin": {
"name": "Skansen",
"type": "ST",
"id": "A=1@O=Skansen@X=18101848@Y=59323673@U=74@L=400110217@",
"extId": "400110217",
"lon": 18.101848,
"lat": 59.323673,
"prognosisType": "PROGNOSED",
"time": "15:58:00",
"date": "2021-04-06",
"rtTime": "15:59:00",
"rtDate": "2021-04-06",
"hasMainMast": true,
"mainMastId": "A=1@O=Skansen (Stockholm)@X=18100895@Y=59323960@U=74@L=300101405@",
"mainMastExtId": "300101405",
"additional": false
},
"Destination": {
"name": "Manilla",
"type": "ST",
"id": "A=1@O=Manilla@X=18133759@Y=59323250@U=74@L=400110141@",
"extId": "400110141",
"lon": 18.133759,
"lat": 59.32325,
"prognosisType": "PROGNOSED",
"time": "16:05:00",
"date": "2021-04-06",
"rtTime": "16:06:00",
"rtDate": "2021-04-06",
"hasMainMast": true,
"mainMastId": "A=1@O=Manilla (Stockholm)@X=18134407@Y=59324185@U=74@L=300101426@",
"mainMastExtId": "300101426",
"additional": false
},
这甚至不是完整 JSON 文件的四分之一,但我认为在这里添加它会太多,如果您想查看整个 JSON 文件,请发表评论
现在,我不专注于更改日期或时间,我只需要一种访问以下数据的方法:
- planningPeriodBegin
- planningPeriodEnd
- The "Origin" "name" (Skansen)
- The "Destination" "name" (Manilla)
我在 YouTube 上复制了一个教程,其中部分介绍了如何访问 JSON 文件 - 但不完全。这是视频的链接: https ://www.youtube.com/watch?v=-gNOVDNWmIg&list=LL&index=1&t=966s
...这是他在视频中写的代码:
import SwiftUI
struct RouteList: View {
@State var gifUrl = String()
@State var searchString = String()
var body: some View {
Text("\(gifUrl)")
.onTapGesture {
let url = URL(string: gifUrl)
guard let GIPHYUrl = url, UIApplication.shared.canOpenURL(GIPHYUrl) else {return}
UIApplication.shared.open(GIPHYUrl)
}
TextField("Search GIFs", text: $searchString)
.multilineTextAlignment(.center)
Button("Fetch Gif"){fetchAPI()}
}
func fetchAPI() {
let apiKey = "xkkakigCSAnCN4Opymed36OoyByZEbBO"
let url = URL(string: "https://api.giphy.com/v1/gifs/search?api_key=\(apiKey)&q=\(self.searchString)&limit=25&offset=0&rating=g&lang=en")
URLSession.shared.dataTask(with: url!) { data, response, error in
if let data = data {
if let decodedGiphy = try? JSONDecoder().decode(GIPHYStructure.self, from: data){
self.gifUrl = decodedGiphy.data[0].url
}
}
}.resume()
}
}
struct GIPHYStructure: Decodable {
let data: [dataStructure]
}
struct dataStructure: Decodable {
let url: String
}
感谢您花时间阅读整篇文章,如果您能设法弄清楚如何去做,那将有很大帮助。我有一个指向 JSON 文件的 URL,但该密钥是私有的。
解决方案
您的 ...Structure 结构需要对您正在解码的 JSON 文件的结构进行建模。所以你会使用这样的东西(未经测试,因为你没有分享 URL):
struct APIStructure: Decodable {
var Trip: [TripStructure]
}
struct TripStructure: Decodable {
var ServiceDays: [ServiceDayStructure]
var LegList: LegListStructure
}
struct ServiceDayStructure: Decodable {
var planningPeriodBegin: Date
var planningPeriodEnd: Date
}
struct LegListStructure: Decodable {
var Leg: [LegStructure]
}
struct LegStructure: Decodable {
var Origin: StationStructure
var Destination: StationStructure
}
struct StationStructure: Decodable {
var name: String
}
然后你可以大致像这样获取和解码 JSON:
func fetchAPI() {
let url = URL(string: "https://api.giphy.com/v1/gifs/search?api_key=\(apiKey)&q=\(self.searchString)&limit=25&offset=0&rating=g&lang=en")
URLSession.shared.dataTask(with: url!) { data, response, error in
if let data = data {
let decoder = JSONDecoder()
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd"
decoder.dateDecodingStrategy = .formatted(formatter)
if let decodedJSON = try? decoder.decode(APIStructure.self, from: data){
// Examples how to access the decoded values:
let firstTripFirstPlanningPeriodBegin: Date = decodedJSON.Trip[0].ServiceDays[0].planningPeriodBegin
let firstTripFirstLegOrigin: String = decodedJSON.Trip[0].LegList.Leg[0].Origin.name
}
}
}.resume()
}
这一切都在本文中更详细地解释:https ://learnappmaking.com/codable-json-swift-how-to/
推荐阅读
- javascript - 未捕获的不变违规:目标容器不是 DOM 元素
- file-upload - Coldfusion 文件上传 cfDocument
- javascript - Mongoose - 无法读取未定义的属性“推送”
- mysql - 加入索引字段不使用索引
- javascript - 将 2 个嵌套对象组合在一起,同时保留两者的属性,同时将重复的键值添加在一起
- excel-formula - 将名字格式更改为姓氏,excel中的名字
- python - 使用scrapy将带有用户附加元素的表格数据放入csv
- android - React Native BLE 错误:设备已断开连接
- flutter - 颤振短信包将短信读取为已读
- embedded-linux - 使用 Zynq,如何在 A53 上运行的嵌入式 Linux 中使用可用的 DMA 之一