0

I've been racking my head for the last day trying to figure out why I'm getting the error below. I've tried changing from an array to a dictionary and no luck.

failure(Swift.DecodingError.keyNotFound(CodingKeys(stringValue: "datalist", intValue: nil), Swift.DecodingError.Context(codingPath: [], debugDescription: "No value associated with key CodingKeys(stringValue: \"datalist\", intValue: nil) (\"datalist\").", underlyingError: nil)))

I'm using Combine and I can see that I'm getting data pack using Postman.

Here's the beginning part of my struct

struct WelcomeList: Codable , Identifiable {
    let id = UUID()
    let datalist: [DATUMVAList]
    let links: Links
    let meta: MetaVAList
}

// MARK: - DATUMVAList
struct DATUMVAList: Codable {
    let id, type: String
    let attributes: AttributesVAList
}

Here's my function and I'm failing at the completion part.

typealias vaNearbyList = [WelcomeList]

    class VAFacilityNearbyList: ObservableObject {
        struct AppError {
            // swiftlint:disable:next identifier_name
            let errorString: String
        }
    
        @Published var vaNearbyList: [WelcomeList] = []
        @Published var errorResponse: String = ""
        var locationIDData: [String] = []
        var cancellabes = Set<AnyCancellable>()
        var appError: AppError? = nil
    
        enum UserFetchError: Error {
            case badServerResponse
            case urlEmpty
            case other
        }
    
        func getNearByVAFacilitiesInfo(idArray: [String]) {
            // We need to create the URL to get the list of facilities
            var vaURL = "https://sandbox-api.va.gov/services/va_facilities/v0/facilities?ids="
            for vaID in idArray {
                vaURL += ",\(vaID)"
            }
            print("\(#function) vaURL \(vaURL)")
    
            var URLBuilder = URLComponents(string: vaURL) //vha_659BZ,vha_544gc
            guard let url = URLBuilder?.url else { return }
    
            var request = URLRequest(url: url)
    //        request.httpMethod = "GET"
            request.setValue(VA_API_Key, forHTTPHeaderField: "apikey")
    
            URLSession.shared.dataTaskPublisher(for: request)
                .subscribe(on: DispatchQueue.global(qos: .background))
                .receive(on: DispatchQueue.main)
                .tryMap { (returnData, response) -> Data in
                    guard
                        let response = response as? HTTPURLResponse,
                          response.statusCode >= 200 && response.statusCode < 300 else {
                              self.appError = AppError(errorString: "\(UserFetchError.badServerResponse)")
                              throw UserFetchError.badServerResponse
                    }
                    print("\(#function) response \(response.statusCode)")
                    print("\(#function) returning data \(returnData)")
                    return returnData
                }
                .decode(type: WelcomeList.self, decoder: JSONDecoder())
                .sink { (completion) in
                    print("\(#function) completion - \(completion)")
                } receiveValue: { [weak self] (returnedVAListData) in
                    print("\(#function) returnedData - \(returnedVAListData)")
                    self?.vaNearbyList = [returnedVAListData]
                }
                .store(in: &cancellabes)
        }
    }

Here's the data I'm getting back. Thanks!

{
    "data": [
        {
            "id": "vha_544GC",
            "type": "va_facilities",
            "attributes": {
                "name": "Rock Hill VA Clinic",
                "facility_type": "va_health_facility",
                "classification": "Primary Care CBOC",
                "website": "https://www.columbiasc.va.gov/locations/RockHill.asp",
                "lat": 34.97720057,
                "long": -81.02445796,
                "time_zone": "America/New_York",
                "address": {
                    "mailing": {},
                    "physical": {
                        "zip": "29732-1836",
                        "city": "Rock Hill",
                        "state": "SC",
                        "address_1": "2670 Mills Park Drive",
                        "address_2": null,
                        "address_3": null
                    }
                },
                "phone": {
                    "fax": "803-325-1612",
                    "main": "803-366-4848",
                    "pharmacy": "888-651-2683",
                    "after_hours": "803-776-4000 x57200",
                    "patient_advocate": "803-776-4000 x56937",
                    "mental_health_clinic": "803-325-9526",
                    "enrollment_coordinator": "803-776-4000 x55815"
                },
                "hours": {
                    "friday": "800AM-430PM",
                    "monday": "800AM-430PM",
                    "sunday": "Closed",
                    "tuesday": "800AM-430PM",
                    "saturday": "Closed",
                    "thursday": "800AM-430PM",
                    "wednesday": "800AM-430PM"
                },
                "operational_hours_special_instructions": null,
                "services": {
                    "other": [],
                    "health": [
                        "Audiology",
                        "Dermatology",
                        "MentalHealthCare",
                        "PrimaryCare",
                        "SpecialtyCare"
                    ],
                    "last_updated": "2022-01-16"
                },
                "satisfaction": {
                    "health": {
                        "primary_care_urgent": 0.7400000095367432,
                        "primary_care_routine": 0.8500000238418579
                    },
                    "effective_date": "2021-03-05"
                },
                "wait_times": {
                    "health": [
                        {
                            "service": "Audiology",
                            "new": 52.25,
                            "established": 2.35
                        },
                        {
                            "service": "Dermatology",
                            "new": 0.125,
                            "established": 2.333333
                        },
                        {
                            "service": "MentalHealthCare",
                            "new": 30.17647,
                            "established": 4.017241
                        },
                        {
                            "service": "PrimaryCare",
                            "new": 14.3125,
                            "established": 1.52759
                        },
                        {
                            "service": "SpecialtyCare",
                            "new": 38.133333,
                            "established": 3.304347
                        }
                    ],
                    "effective_date": "2022-01-16"
                },
                "mobile": false,
                "active_status": "A",
                "operating_status": {
                    "code": "NORMAL"
                },
                "detailed_services": null,
                "visn": "7"
            }
        }
    ],
    "links": {
        "self": "https://sandbox-api.va.gov/services/va_facilities/v0/facilities?ids=vha_544GC&page=1&per_page=10",
        "first": "https://sandbox-api.va.gov/services/va_facilities/v0/facilities?ids=vha_544GC&page=1&per_page=10",
        "prev": null,
        "next": null,
        "last": "https://sandbox-api.va.gov/services/va_facilities/v0/facilities?ids=vha_544GC&page=1&per_page=10"
    },
    "meta": {
        "pagination": {
            "current_page": 1,
            "per_page": 10,
            "total_pages": 1,
            "total_entries": 1
        },
        "distances": []
    }
}
Robert
  • 809
  • 3
  • 10
  • 19
  • 1
    In order for this to be debugged, you would need to show the data you’re trying to parse. – jnpdx Jan 29 '22 at 01:32
  • 2
    Your JSON doesn’t match, like the error says. See how they JSON says “data” and your model says “datalist”? There may be other errors, but that was the first one I spotted. Paste your JSON into app.quicktype.io and compare your models. – jnpdx Jan 29 '22 at 02:12
  • Ah let me explore that. I was using quicktype for a couple different structs and I changed the name for redeclaration error. Thank you – Robert Jan 29 '22 at 02:31
  • So I made this change, but now I get the error `"Expected to decode Array but found a dictionary instead."` which doesn't make sense since I'm not decode is not of an array type `.decode(type: WelcomeList.self` – Robert Jan 29 '22 at 15:56
  • You’d have to show your complete code for your models that you’re trying to debug this. Is it exactly what QuickType is spitting out? – jnpdx Jan 29 '22 at 17:07

1 Answers1

0

You're telling the decoder to decode something that has the fields of a WelcomeList:

let id = UUID()
let datalist: [DATUMVAList]
let links: Links
let meta: MetaVAList

The top level keys in your JSON are:

{
  "data": ...
  "links": ...
  "meta": ...
}

The error is telling you it is looking for a key named datalist and can't find one.

To solve the problem you're either going to have to rename the field to data or use CodingKeys to tell the system that the field of your struct named datalist is found with a key named data.

See the Encoding and Decoding documentation under the heading "Choose Properties to Encode and Decode Using Coding Keys"

Scott Thompson
  • 22,629
  • 4
  • 32
  • 34