首页 > 解决方案 > 我在 JSON 文件中嵌套了数据,并且正在使用嵌套结构。如何快速访问嵌套在第一个结构中的值

问题描述

这是我的代码。我正在从 CalorieNinjas API 中提取 JSON 数据:

 struct Result: Codable {
     
     var items: [FoodItem]?
     
 }

struct FoodItem: Codable {
    var name: String?
    var calories: String?
}

 public class API {
     
     func apiRequest(search: String, completion: @escaping (Result) -> ()) {
         
         //URL
         var query = search.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
         let url = URL(string: "https://calorieninjas.p.rapidapi.com/v1/nutrition?query=" + query!)
         
         //URL REQUEST
         var request = URLRequest(url: url!, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 10.0)
         
         //Specify header
         let headers = [
             "x-rapidapi-key": "3be44a36b7msh4d4738910c1ca4dp1c2825jsn96bcc44c2b19",
             "x-rapidapi-host": "calorieninjas.p.rapidapi.com"
         ]
         
         request.httpMethod="GET"
         request.allHTTPHeaderFields = headers
         
         //Get the URLSession
         let session = URLSession.shared
         
         //Create data task
         let dataTask = session.dataTask(with: request) { (data, response, error) in
             
             let result = try? JSONDecoder().decode(Result.self, from: data!)
            print(result)
             DispatchQueue.main.async {
                 completion(result!)
             }
              
             
         }
         
         //Fire off data task
         dataTask.resume()
         
     }
 }

这就是我的看法:

struct ContentView: View {
    
    @State var result = Result()
    @State private var searchItem: String = ""
    
    var body: some View {
        ZStack(alignment: .top) {
            Rectangle()
                .fill(Color.myPurple)
                .ignoresSafeArea(.all)
            VStack {
                TextField("Enter food", text: $searchItem)
                    .background(Color.white)
                    .padding()
                    .textFieldStyle(RoundedBorderTextFieldStyle())
                SearchButton()
                    .padding(.top)
                    .onTapGesture {
                        API().apiRequest(search: searchItem, completion: { (result) in
                            self.result = result
                        })
                    }
            }
        }
    }
}

这是我的打印语句的结果到终端的输出,所以我知道我的数据正在被获取和存储:

Optional(CalorieCountApp.Result(items: Optional([CalorieCountApp.FoodItem(name: Optional("pizza"), calories: Optional(262.9))])))

我试图做的是类似于 Text 的东西,(result.items.name/calories)但我无法访问这样的变量。我是 swift 的新手,并且将应用程序作为一个整体制作,非常感谢任何帮助

标签: jsonswiftapistructswiftui

解决方案


看起来你有几个Optionals ,这意味着你可能会使用?操作符来解开它们。

鉴于您的类型,这应该有效:

let index = 0
let name = result?.items?[index].name // will be `String?`
let calories = result?.items?[index].calories // according to your code you provided, this says `String?` but in your console output it looks like `Double?`

或在您的示例中:

Text(result?.items?[index].name ?? "unknown")

您可能想多阅读一些关于展开 Optionals 或nil在 Swift 中处理的内容——有几种不同的策略。例如,您可以看到我??在最后一个示例中使用了那里。

这是一个有用的链接:https ://www.hackingwithswift.com/sixty/10/2/unwrapping-optionals


推荐阅读