在 swift 中对动态键和动态对象使用 Codable
Posted
技术标签:
【中文标题】在 swift 中对动态键和动态对象使用 Codable【英文标题】:Using Codable on a dynamic key and dynamic object in swift 【发布时间】:2019-11-15 13:41:08 【问题描述】:我在从服务调用返回的结构中嵌套了以下结构,但我无法对这部分进行编码/解码。我遇到的问题是 customKey 和 customValue 都是动态的。 customValue 可以是数组或字典或字典数组 例如
"status": "a string value",
"id": "a string value",
"property":
"customkey1": "customValue1",
"customKey2": [
"InnerCustomKey": "InnerCustomValue"
,
"InnerCustomKey": "InnerCustomValue"
,
"InnerCustomKey": "InnerCustomValue"
],
"customkey3":
"InnerCustomKey": "InnerCustomValue"
我尝试了类似 var values: [String:String] 但它在另一个对象中失败。 我按照答案Using Codable on a dynamic type/object 但没有成功
【问题讨论】:
customValue
[reasonable] 的选项是有限的吗?
是所有可能的变体(字符串、数组、字典、字典数组)并且都是字符串类型的最内层值吗?
@user28434 customValue 有任何值(字符串、数组、字典、字典数组等)
【参考方案1】:
extension KeyedDecodingContainerProtocol
func getValueFromAvailableKey(codingKeys:[CodingKey])-> Any?
for key in codingKeys
for keyPath in self.allKeys
if key.stringValue == keyPath.stringValue
do
if let value = try? self.decodeIfPresent([String].self, forKey:keyPath)
return value
if let value = try? self.decodeIfPresent([String:String].self, forKey:keyPath)
return value
if let value = try? self.decodeIfPresent([[String:String]].self, forKey:keyPath)
return value
if let value = try? self.decodeIfPresent(String.self, forKey:keyPath)
return value
return nil
return nil
private struct CustomCodingKeys: CodingKey
var stringValue: String
init?(stringValue: String)
self.stringValue = stringValue
var intValue: Int?
init?(intValue: Int)
return nil
struct CustomModel: Codable
var status:String?
var id: String?
var property: Property?
init(from decoder: Decoder)
do
let container = try decoder.container(keyedBy: CustomCodingKeys.self)
status = try container.decodeIfPresent(String.self, forKey: CustomCodingKeys.init(stringValue: "status")!)
id = try container.decodeIfPresent(String.self, forKey: CustomCodingKeys.init(stringValue: "id")!)
property = try container.decodeIfPresent(Property.self, forKey: CustomCodingKeys.init(stringValue: "property")!)
catch
print(error.localizedDescription)
func encode(to encoder: Encoder) throws
var container = encoder.container(keyedBy: CustomCodingKeys.self)
try? container.encodeIfPresent(self.status, forKey: CustomCodingKeys.init(stringValue: "status")!)
try? container.encodeIfPresent(self.id, forKey: CustomCodingKeys.init(stringValue: "id")!)
try? container.encodeIfPresent(self.property, forKey: CustomCodingKeys.init(stringValue: "property")!)
// MARK: - Property
struct Property: Codable
var customkey:[String:Any?] = [:]
init(from decoder: Decoder)
do
let container = try decoder.container(keyedBy: CustomCodingKeys.self)
for key in container.allKeys
customkey[key.stringValue] = container.getValueFromAvailableKey(codingKeys: [CustomCodingKeys.init(stringValue: key.stringValue)!])
catch
print(error.localizedDescription)
func encode(to encoder: Encoder) throws
var container = encoder.container(keyedBy: CustomCodingKeys.self)
for key in customkey
try? container.encodeIfPresent(customkey[key.key] as? String, forKey: CustomCodingKeys.init(stringValue: key.key)!)
try? container.encodeIfPresent(customkey[key.key] as? [[String:String]], forKey: CustomCodingKeys.init(stringValue: key.key)!)
try? container.encodeIfPresent(customkey[key.key] as? [String:String], forKey: CustomCodingKeys.init(stringValue: key.key)!)
希望对你有帮助!
【讨论】:
您的示例代码可以很好地解码,但没有编码功能您也请添加编码代码吗? 你想怎么编码???你想编码相同的 json 吗?? 是的,我首先解码由您的示例完成的 json 字符串,然后添加一些数据,然后将该数据编码为 json。为此,我必须将属性扩展为编码 @Mahesh 我也重新编辑了编码的答案问候,以上是关于在 swift 中对动态键和动态对象使用 Codable的主要内容,如果未能解决你的问题,请参考以下文章