Search code examples
jsonswiftjsondecoder

Decoder not decoding json at keypath


Im trying to decode some JSON, but it's not parsing it. I think it may have something to to with either an incorrect KeyPath or the object itself. But I cannot figure it out.

This is the JSON that I want to decode (I want the array inside the docs path):

{
    "status": 200,
    "data": {
        "docs": [
            {
                "_id": "60418a6ce349d03b9ae0669e",
                "title": "Note title",
                "date": "2015-03-25T00:00:00.000Z",
                "body": "this is the body of my note.....",
                "userEmail": "[email protected]"
            }
        ],
        "total": 1,
        "limit": 20,
        "page": 1,
        "pages": 1
    },
    "message": "Notes succesfully Recieved"
}

Here's my decode function:

extension JSONDecoder {
    func decode<T: Decodable>(_ type: T.Type, from data: Data, keyPath: String) throws -> T {
        let toplevel = try JSONSerialization.jsonObject(with: data)
        if let nestedJson = (toplevel as AnyObject).value(forKeyPath: keyPath) {
            let nestedJsonData = try JSONSerialization.data(withJSONObject: nestedJson)
            return try decode(type, from: nestedJsonData)
        } else {
            throw DecodingError.dataCorrupted(.init(codingPath: [], debugDescription: "Nested json not found for key path \"\(keyPath)\""))
        }
    }
}

And i'm calling it like this:

let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let notes = try decoder.decode([Note].self, from: data, keyPath: "data.docs")

Finally, this is my Note Struct:

struct Note: Codable {
    var title: String?
    let date: Date?
    var body: String?
    let userEmail: String?
}

Solution

  • The problem was that I was trying to decode date as a Date object instead of a String as is shown on the JSON.

    Thanks @vadian!