Swift Decodable,端点返回完全不同的类型 [英] Swift Decodable, Endpoint returns completely different types

查看:279
本文介绍了Swift Decodable,端点返回完全不同的类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在使用我正在使用的API的情况下,根据调用是否成功,一个API端点可以返回完全不同的响应.
如果成功,API端点将在根中返回一个请求的对象数组,如下所示:

With API I'm working with, I have a case where 1 API Endpoint can return completely different responses, based on if the call was successful or not.
In case of success, API Endpoint returns an Array of requested objects, in the root, something like this:

[
    {
        "key1": "value1",
        "key2": "value2",
        "key3": "value3"
    },
    {
        "key1": "value1",
        "key2": "value2",
        "key3": "value3"
    },
    ...
]

我通常用try JSONDecoder().decode([Object].self, from: data)

如果出现错误,API端点将返回完全不同的内容,如下所示:

In case of an error, API Endpoint returns something completely different, looks like this:

{
    "error": "value1",
    "message": "value2",
    "status": "value3"
}

并使用try JSONDecoder().decode([Object].self, from: data)解码通常会失败.

and decoding with try JSONDecoder().decode([Object].self, from: data) normally fails.

现在,我的问题是,有没有一种方法可以解码错误响应密钥,这种方式(我会说不是通常构建的API)没有创建一个我称之为的 plural 对象,名为Objects,该对象将具有可选属性errormessagestatus,例如objects.
我的想法扩展了数组where Element == Object,并以某种方式尝试解码errormessagestatus,但是我遇到了Conformance of 'Array<Element>' to protocol 'Decodable' was already stated in the type's module 'Swift'.也许不可能那样做,所以任何其他甚至完全不同的建议都将受到欢迎.

Now, my question is, is there a way, to decode error response keys, in this kind of (I would say not so normally architectured API), WITHOUT creating a -what I call- plural object named Objects that would have optional properties error, message, status, and for example objects.
My thinking got somewhere to extending Array where Element == Object and somehow trying to decode error, message, status, but I'm hitting Conformance of 'Array<Element>' to protocol 'Decodable' was already stated in the type's module 'Swift'. Maybe it's not even possible to do it that way, so any other, even completely different, suggestion would be very welcome.

推荐答案

我的建议是将JSON的根对象解码为具有关联类型的枚举

My suggestion is to decode the root object of the JSON as enum with associated types

struct Item : Decodable {
    let key1, key2, key3 : String
}

struct ResponseError  : Decodable {
    let error, message, status : String
}

enum Response : Decodable {
    case success([Item]), failure(ResponseError)

    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        do {
            self = .success(try container.decode([Item].self))
        } catch DecodingError.typeMismatch {
            self = .failure(try container.decode(ResponseError.self))
        }
    }
}

并使用它

do {
    let result = try JSONDecoder().decode(Response.self, from: data)
    switch result {
        case .success(let items): print(items)
        case .failure(let error): print(error.message)
    }
} catch {
    print(error)
}

优良作法是仅捕获特定的.typeMismatch错误,并将其他错误立即移交给调用方.

It's good practice to catch only the specific .typeMismatch error and hand over other errors instantly to the caller.

这篇关于Swift Decodable,端点返回完全不同的类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆