У меня есть ситуация, когда сервер отправляет мне модель, в которой я знаю типы и имена некоторых ключей, а не другие. Однако пользователь может редактировать эти другие пары ключ-значение по своему усмотрению.
Пример:
{ "a": "B",
"b": 42,
"__customKey1": "customVal1",
"__customKey2": [41, 42],
"__customKey3": {"z":"x"}
}
Итак, в итоге я хочу получить модель с некоторыми объявленными свойствами и некоторыми значениями, помещенными в Dictionary<String, Any>
, например.
struct MyStruct {
var a: String?
var b: Int?
var dict: Dictionary<String,Any>
}
Я пробовал что-то вроде:
public struct CodingKeysX: CodingKey {
public var intValue: Int?
public var stringValue: String
public init?(intValue: Int) { self.intValue = intValue; self.stringValue = "\(intValue)" }
public init?(stringValue: String) { self.stringValue = stringValue }
static func make(key: String) -> CodingKeysX {
return CodingKeysX(stringValue: key)!
}
}
init(from decoder: Decoder) throws {
let co = try! decoder.container(keyedBy: CodingKeysX.self)
let container = try decoder.container(keyedBy: CodingKeys.self)
self.a = try container.decode(String?.self, forKey: .a)
self.b = try container.decode(Int?.self, forKey: .b)
let allDeclaredKeys = container.allKeys.map({ $0.stringValue })
self.dict = Dictionary<String, Any>()
for key in co.allKeys.filter({ !allDeclaredKeys.contains($0.stringValue) }) {
self.dict[key.stringValue] = try? co.decodeIfPresent(Any.self, forKey: key)
}
}
Но я получаю следующую ошибку времени компиляции:
Тип протокола «Любой» не может соответствовать «Декодируемому», поскольку только конкретные типы могут соответствовать протоколам.
Также кажется, что с помощью JSONDecoder
я не могу получить ссылку на оригинал Data
нам NSJSONSerialization
. Так что я мог бы, я полагаю, сделать это наоборот, когда я сначала инициализирую dict, используя более старую технику, затем инициализирую модель, используя JSONDecoder
, и заменяю init чем-то, что передает данные, но это просто кажется неправильным, потому что мы были бы эффективно десериализация дважды :/