Декодирование API SwiftUI

#function #api #swiftui

#функция #API #swiftui

Вопрос:

Я пытаюсь расшифровать ответ JSON от Yelp на бизнес-детали. Ответ JSON возвращается следующим образом:

 {
"id": "ATaQ4GLQisXA7tylsJobhQ",
"alias": "chicken-fire-orlando",
"name": "Chicken Fire",
"image_url": "https://s3-media4.fl.yelpcdn.com/bphoto/YMkiKEv-WApzbJZ321rsEg/o.jpg",
"is_claimed": true,
"is_closed": false,
"url": "https://www.yelp.com/biz/chicken-fire-orlando?adjust_creative=s-hyKAjsx6P4UW-uqMn7aQamp;utm_campaign=yelp_api_v3amp;utm_medium=api_v3_business_lookupamp;utm_source=s-hyKAjsx6P4UW-uqMn7aQ",
"phone": "",
"display_phone": "",
"review_count": 107,
"categories": [
    {
        "alias": "chickenshop",
        "title": "Chicken Shop"
    }
],
"rating": 5.0,
"location": {
    "address1": "2406 E Washington St",
    "address2": "",
    "address3": null,
    "city": "Orlando",
    "zip_code": "32803",
    "country": "US",
    "state": "FL",
    "display_address": [
        "2406 E Washington St",
        "Orlando, FL 32803"
    ],
    "cross_streets": ""
},
"coordinates": {
    "latitude": 28.5438637820401,
    "longitude": -81.3516076281667
},
"photos": [
    "https://s3-media4.fl.yelpcdn.com/bphoto/YMkiKEv-WApzbJZ321rsEg/o.jpg",
    "https://s3-media3.fl.yelpcdn.com/bphoto/gLcMNuoaJonieGFsSS9qeA/o.jpg",
    "https://s3-media4.fl.yelpcdn.com/bphoto/oWAPiL4nQLab-PrrEoQ30A/o.jpg"
],
"hours": [
    {
        "open": [
            {
                "is_overnight": false,
                "start": "1200",
                "end": "1500",
                "day": 3
            },
            {
                "is_overnight": false,
                "start": "1700",
                "end": "2000",
                "day": 3
            },
            {
                "is_overnight": false,
                "start": "1200",
                "end": "1500",
                "day": 4
            },
            {
                "is_overnight": false,
                "start": "1700",
                "end": "2000",
                "day": 4
            },
            {
                "is_overnight": false,
                "start": "1200",
                "end": "1500",
                "day": 5
            },
            {
                "is_overnight": false,
                "start": "1700",
                "end": "2000",
                "day": 5
            },
            {
                "is_overnight": false,
                "start": "1200",
                "end": "1500",
                "day": 6
            },
            {
                "is_overnight": false,
                "start": "1700",
                "end": "2000",
                "day": 6
            }
        ],
        "hours_type": "REGULAR",
        "is_open_now": true
    }
],
"transactions": [
    "delivery",
    "pickup"
]
}
  

Для простоты я просто хочу отменить 3 простых вещи.

 struct BusinessDetails: Codable, Identifiable {
    let id: String
    let name: String
    let image_url: String
}


public class Api: ObservableObject {
    func getDetails(completion: @escaping (BusinessDetails) -> ()) {
        let apikey = "API KEY HERE"
        let url = URL(string: "https://api.yelp.com/v3/businesses/ATaQ4GLQisXA7tylsJobhQ")!
        var request = URLRequest(url: url)
        request.setValue("Bearer (apikey)", forHTTPHeaderField: "Authorization")
        request.httpMethod = "GET"
        
        URLSession.shared.dataTask(with: request) {(data, _, _) in
            let details = try! JSONDecoder().decode(BusinessDetails.self, from: data!)
            
            DispatchQueue.main.async {
                completion(details)
                print("Below are details")
                print(details)
            }
        }.resume()
    }
}
  

И я вижу, что я могу получить информацию, которую я хочу отобразить в своем представлении, но у меня, очевидно, неправильный синтаксис при вызове моей функции.

Я использую:

 import SwiftUI
import SDWebImageSwiftUI

struct Details: View {
    @State var details: [BusinessDetails] = []
    
    var body: some View {
        ScrollView (/*@START_MENU_TOKEN@*/.vertical/*@END_MENU_TOKEN@*/, showsIndicators: false) {
            ForEach(details) { detail in
                VStack {
                    WebImage(url: URL(string: detail.image_url))
                        .onSuccess { image, data, cacheType in
                    }
                    .resizable()
                    .placeholder(Image(systemName: "photo"))
                        
                    .placeholder {
                        Rectangle().foregroundColor(.gray)
                    }
                    .indicator(.activity)
                    .transition(.fade(duration: 0.5))
                    .scaledToFill()
                    .frame(minWidth: 0, maxWidth: .infinity, minHeight: 100, maxHeight: 250)
                    .clipped()
                }.padding(.vertical, 8)
            }.onAppear {
                Api().getDetails { (details) in
                    self.details = details
                }
            }
        }
        
    }
}
  

Печать в моей функции показывает:

 "BusinessDetails(id: "ATaQ4GLQisXA7tylsJobhQ", name: "Chicken Fire", image_url: "https://s3-media4.fl.yelpcdn.com/bphoto/YMkiKEv-WApzbJZ321rsEg/o.jpg")"
  

Комментарии:

1. Я не понимаю, в чем ваш вопрос. Единственное, что напоминает проблему / вопрос, это предложение «но у меня, очевидно, синтаксис при неправильном вызове моей функции» — о каком синтаксисе вы говорите

2. Ошибка в моем заявлении onAppear. Он не возвращает никаких данных на мой взгляд.

3. «Невозможно присвоить значение типа ‘BusinessDetails’ типу [BusinessDetails]

4. свойство details вашего Details представления представляет собой массив. Итак, либо измените его на просто тип BusinessDetails , либо добавьте к этому массиву self.details.append(details) в блоке завершения