Hızlı Çözülebilir - genel türden nasıl kaçınılır?

Aug 19 2020

JSON REST API'mden karmaşık bir iç içe geçmiş nesne alıyorum.

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

Sanırım bununla başa çıkmanın doğru yolu, genel bir tür tanıtmaktır.

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

... ama öyle bile olsa, valueskarışık bir dizi olabilir, bu yüzden neyin işe Vyarayacağını bildirmenin nasıl yardımcı olacağını anlamıyorum .

Ama sonra, tabii ki jenerik tür, hiyerarşinin sonuna kadar, DocumentDraftnesneye, yayıncıya, API çağrılarıma vs. yayılır , aksi takdirde çok temiz ve okunabilir çağrılar ve nesneler zincirinin tamamını kirletir. Bununla yalnızca düzeyinde ilgilenmek Valueve JSONDecoder'ın bir şekilde ikisinden birini döndürmesine izin vermek istiyorum.

Üst nesnenin tamamını değiştirmeden valya Stringda [String]değiştirmeden isteğe bağlı olanın iki olasılığını ele almanın başka bir yolu var mı ?

Yanıtlar

4 gcharita Aug 19 2020 at 12:31

Bunu yalnızca [String]türü kullanarak ve aşağıdaki gibi protokol init(from:)işlevini manuel olarak uygulayarak elde edebilirsiniz Decodable:

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)
        }
    }
}

Değere kod çözme işlemi Stringbaşarılı olduğunda, yalnızca bir öğe içeren bir dizi dizisi oluşturun. StringDeğerin kodunu çözme başarısız olduğunda,[String]