Swift Decodable-如何避免泛型? [英] Swift Decodable - how to avoid generic type?

查看:86
本文介绍了Swift Decodable-如何避免泛型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在从JSON REST API中检索复杂的嵌套对象。

I am retrieving a complex nested object from my JSON REST API.

DocumentDraft
 - uuid: String
 - schema: Schema // Very complicated object with many variations
 - url: String
 - values: [Value]
 - successors: [String]
 - predecessors: [String]

Value
 - key: String
 - val: String? OR [String]?   // <-- This is the problem

我想解决这个问题的正确方法是引入泛型

I suppose the proper way to deal with this is to introduce a generic type.

struct Value<V: Decodable>: Decodable {
  let key: String
  let val: V?
}

...但即使如此,可能是一个混合数组,所以我看不出声明 V 有什么帮助。

... but even so, values could be a mixed array, so I do not see how declaring what V is would help.

但是,当然,泛型类型一直沿层次结构传播,一直传播到 DocumentDraft 对象,发布者,我的API调用等。污染了否则非常干净易读的调用的整个链和对象。我只想在 Value 级别上处理此问题,然后让JSONDecoder简单地以某种方式返回两个值之一。

But then, of course the generic type propagates all the way up the hierarchy, to the DocumentDraft object, to the publisher, to my API calls, etc. polluting the entire chain of otherwise very clean and readable calls and objects. I would like to deal with this only on the level of Value, and let the JSONDecoder simply return one of the two somehow.

还有另一种方式来处理可选的 val 作为 String 的两种可能性[String] 而不更改整个父对象?

Is there another way to deal with the two possibilities of the optional val as either String or [String] without changing the entire parent object?

推荐答案

您可以仅使用 [String] 类型并手动实现 Decodable init(from:)函数c $ c>协议,例如:

You can achieve that using only the [String] type and manually implementing the init(from:) function of Decodable protocol like this:

struct Value: Decodable {
    let key: String
    let val: [String]?
    
    enum CodingKeys: String, CodingKey {
        case key, val
    }
    
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        
        key = try container.decode(String.self, forKey: .key)
        do {
            if let string = try container.decodeIfPresent(String.self, forKey: .val) {
                val = [string]
            } else {
                val = nil
            }
        } catch DecodingError.typeMismatch {
            val = try container.decodeIfPresent([String].self, forKey: .val)
        }
    }
}

成功解码为 String 值后,创建仅包含一个元素的字符串数组。当解码为 String 值失败时,请尝试解码为 [String]

When decoding to String value succeeds, create an array of strings with only one element. When decoding to String value fails, try to decode as [String]

这篇关于Swift Decodable-如何避免泛型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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