KeyDecodingStrategy .convertFromSnakeCase не работает - PullRequest
0 голосов
/ 21 марта 2020

У меня есть класс адаптера с именем ServiceHealthApi, который имеет эту функцию:

final class ServiceHealthApi {
    let mockApi = "https://staging.myapp.com/health"

    func getHealth() -> Single<ServiceHealthResponseModel> {
        let url = URL(string: mockApi)
        guard let validUrl = url else { return .never() }

        var urlRequest = URLRequest(url: validUrl)
        urlRequest.httpMethod = "GET"
        let headers = [
            "Content-Type" : "application/json; charset=utf-8"
        ]
        urlRequest.allHTTPHeaderFields = headers
        return URLSession.shared.rx.data(request: urlRequest)
            .take(1)
            .map {
                let decoder = JSONDecoder()
                decoder.keyDecodingStrategy = .convertFromSnakeCase
                return try JSONDecoder().decode(ServiceHealthResponseModel.self, from: $0) }
            .asSingle()

    }
}

struct HealthResponseModel: Decodable {
    struct DataResponse: Decodable {
        let serviceName: String
        let serviceStatus: String
        let serviceOperational: Bool
    }

    struct Meta: Decodable {
        let statusCode: Int
        let statusMessage: String
    }

    let data: [DataResponse]
    let meta: Meta
}

Строка JSON, которая должна быть проанализирована, выглядит так:

{
    "data": [
        {
            "service_name": "web",
            "service_status": "UP",
            "service_operational": true
        },
        {
            "service_name": "orm",
            "service_status": "UP",
            "service_operational": true
        }
    ],
    "meta": {
        "status_code": 200,
        "status_message": "OK"
    }
}

Теперь, когда я попытался запустить свой интеграционный тест, он не смог с этой ошибкой из JSONDecoder:

error keyNotFound (CodingKeys (stringValue: "serviceName", intValue: nil), Swift.DecodingError .Context (codingPath: [CodingKeys (stringValue: "data", intValue: nil), _JSONKey (stringValue: "Index 0", intValue: 0)], debugDescription: "Нет значения, связанного с ключом CodingKeys (stringValue: \" serviceName \ ", intValue: nil) (\" serviceName \ ").", underError: nil))

Самое смешное, если я отключил .convertFromSnakeCase и просто использовал camelcase для имен переменных в модель ответа, она работала просто отлично. Я знаю, что, вероятно, могу использовать ключи кодирования, но мне просто интересно, почему моя реализация не сработала?

Заранее спасибо.

PS: я попытался разобрать JSON Строка напрямую, без вызова API, и это сработало.

1 Ответ

3 голосов
/ 21 марта 2020

Вы создаете секунду JSONDecoder без какой-либо стратегии

Замените

let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
return try JSONDecoder().decode(ServiceHealthResponseModel.self, from: $0) }

на

let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
return try decoder.decode(ServiceHealthResponseModel.self, from: $0) }
...