Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Decoding Dictionary #220

Open
MartinP7r opened this issue Jul 10, 2021 · 0 comments
Open

Decoding Dictionary #220

MartinP7r opened this issue Jul 10, 2021 · 0 comments

Comments

@MartinP7r
Copy link
Contributor

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant