1

I'm using this library which has created non-empty collections like arrays, dictionaries and strings. https://github.com/pointfreeco/swift-nonempty

When I decode to the non-empty array I get the following error

Swift.DecodingError.typeMismatch(Swift.Dictionary, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "poiList", intValue: nil)], debugDescription: "Expected to decode Dictionary but found an array instead.", underlyingError: nil))

This is my structure

struct LocationCarModel: Codable {

    // MARK: - Properties
    var poiList: NonEmptyArray<PointOfInterest>

    // MARK: - PointOfInterest
    struct PointOfInterest: Codable {
        var id: Int
        var coordinate: Position
        var fleetType: String
        let numberPlate = "HCD837EC"
        let model: String = "Tesla S"
        let fuel: Double = 0.9
    }
}

This is the response I'm getting https://fake-poi-api.mytaxi.com/?p2Lat=53.394655&p1Lon=9.757589&p1Lat=53.694865&p2Lon=10.099891

and this how I'm decoding it.

 public extension Decodable {

   static func parse(from item: Any?, strategy: JSONDecoder.KeyDecodingStrategy = .useDefaultKeys) -> Self? {

       guard let data = self.data(from: item) else {
           return nil
       }

       let decoder = JSONDecoder()
       decoder.keyDecodingStrategy = strategy

       do {
           let result = try decoder.decode(Self.self, from: data)
           return result
       } catch {
           debugPrint(error)
           return nil
       }
   }

   private static func data(from item: Any?) -> Data? {
       switch item {
       case let data as Data:
           return data
       case let string as String:
           return string.data(using: .utf8)
       case .some(let item):
           return try? JSONSerialization.data(withJSONObject: item, options: [])
       case nil:
           return nil
       }
   }
}

and the line to decode using the above function is

let model = LocationCarModel.parse(from: data)

Changing poiList to the standard swift array then no error occurs.

Any ideas how I can solve this issue? Any help would be appreciated. Thank you in advance.

0

2 Answers 2

1

You need to have your own init(from:) for the top struct since JSONDecoder doesn't understand NonEmpty and how to initialise it. Apart from the init I also added coding keys and a new error

enum DecodeError: Error {
    case arrayIsEmptyError
}

struct LocationCarModel: Codable {
    var poiList: NonEmpty<[PointOfInterest]>

    enum CodingKeys: String, CodingKey {
        case poiList
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        let array = try container.decode([PointOfInterest].self, forKey: .poiList)
        guard let first = array.first else {
            throw DecodeError.arrayIsEmptyError
        }
        poiList = NonEmptyArray(first, array)
    }
    //...
}
Sign up to request clarification or add additional context in comments.

Comments

0

You can try

struct Root: Codable {
    let poiList: [PoiList]
}

// MARK: - PoiList
struct PoiList: Codable {
    let id: Int
    let coordinate: Coordinate
    let fleetType: String
    let heading: Double
}

// MARK: - Coordinate
struct Coordinate: Codable {
    let latitude, longitude: Double
}

let res = try? JSONDecoder().decode(Root.self,from:data)
print(res)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.