XMLCoder
XMLCoder copied to clipboard
Decoding Dictionary
This might be more general Codable related problem. Please let me know if you think it's beyond the scope of this project.
I have some xml data that looks like this:
<some_type>
// ....
<q_codes>
<q_code type="a">123</q_code>
<q_code type="b">456</q_code>
<q_code type="c">789</q_code>
<q_code type="d">0</q_code>
</q_codes>
</some_type>
Which seems to me would be most fitting to decode into a dictionary, like
["a": 123, "b": 456, "c": 789, "d": 0]
Inside the parent struct:
struct SomeType: Codable, ... {
// ...
let qCodes: [String: Int]
}
However, I haven't found a clean way to do this with normal container decoding and XMLCoder. What I am currently doing is using a stand-in struct with NodeEncoding that's basically private to SomeType and just used to decompose the xml structure and somewhat awkwardly transform it into a dictionary inside init(from decoder: Decoder):
struct QCode: Codable, DynamicNodeEncoding {
let value: Int
let type: String
enum CodingKeys: String, CodingKey {
case value = "", type = "rad_type"
}
static func nodeEncoding(for key: CodingKey) -> XMLEncoder.NodeEncoding {
switch key {
case CodingKeys.type: return .attribute
default: return .element
}
}
}
// ...
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let qCodeData = try container.decodeIfPresent(QCode.self, forKey: .qCodes)
qCodes = qCodeData?.qCode.reduce(into: [String: Int](), { $0[$1.type] = $1.value }) ?? [:]
// ...
}
I was wondering if there's a better approach to decoding dictionary-like xml structures like these.