XMLCoder
XMLCoder copied to clipboard
Is there support for Heterogeneous collections?
I'd love to use this library, just want to make sure there is support for heterogeneous collections before I begin integrating it.
I am getting a response back from an API that is serving two different kinds of responses and I need to be able to decode them both and put them into a single container. I could used a super class but then I would lose all the access to other properties. My original thought is that this might be able to be done with a Protocol of some sort?
Vehicle 1:
<LatestInfoTable>
<AgencyVehicleName>1921</AgencyVehicleName>
<RouteShortName>HWB</RouteShortName>
<BlockID>c8bdfbe2-72e9-4870-81a6-d7cb8cd4263f</BlockID>
<TripID>e15aed4d-f527-47a7-a4d5-f44fa59838de</TripID>
<IsTripper>N</IsTripper>
<PatternName>Hethwood B</PatternName>
<TripStartTime>2019-04-17T12:45:00-04:00</TripStartTime>
<LastStopName>Torgersen Hall</LastStopName>
<StopCode>1114</StopCode>
<Rank>0</Rank>
<IsBusAtStop>Y</IsBusAtStop>
<IsTimePoint>Y</IsTimePoint>
<LatestEvent>2019-04-17T12:46:35-04:00</LatestEvent>
<LatestRSAEvent>2019-04-17T12:46:31-04:00</LatestRSAEvent>
<Latitude>50.22935</Latitude>
<Longitude>-74.42052</Longitude>
<Direction>308</Direction>
<Speed>1</Speed>
<TotalCount>0</TotalCount>
<PercentOfCapacity>0</PercentOfCapacity>
</LatestInfoTable>
Vehicle 2:
<LatestInfoTable>
<AgencyVehicleName>6412</AgencyVehicleName>
<LatestEvent>2019-04-17T09:33:45-04:00</LatestEvent>
<Latitude>50.19622</Latitude>
<Longitude>-74.39557</Longitude>
<Direction>252</Direction>
<Speed>6</Speed>
</LatestInfoTable>
I'd like to be able to have something like this
struct Resonse: Decodable {
var vehicles: [Vehicles]
enum CodingKeys: String, CodingKey {
var vehicles = "LatestInfoTable"
}
}
Hi @mhs2342, thank you for considering XMLCoder!
I see multiple options here. Would any of these fit your use case well?
- Decode as a dictionary:
let decoder = XMLDecoder()
let decoded1 = try decoder.decode([String: String].self, from: vehicle1)
let decoded2 = try decoder.decode([String: String].self, from: vehicle2)
- Decode to one struct with optional properties:
struct OptionalProperties: Decodable {
let agencyVehicleName: String
let latestEvent: String
let latitude: Double
let longitude: Double
let direction: Int
let speed: Int
let routeShortName: String?
let blockID: String?
let isTripper: Bool?
let patternName: String?
let tripStartTime: String?
let lastStopName: String?
let stopCode: Int?
let isBusAtStop: Bool?
let isTimePoint: Bool?
let latestRSAEvent: String?
let totalCount: Int?
let percentOfCapacity: Int?
}
let decoder = XMLDecoder()
decoder.keyDecodingStrategy = .convertFromCapitalized
let decoded1 = try decoder.decode(OptionalProperties.self, from: vehicle1)
let decoded2 = try decoder.decode(OptionalProperties.self, from: vehicle2)
- Decode to multiple structs with non-optional properties:
struct VehicleProperties: Decodable {
let agencyVehicleName: String
let latestEvent: String
let latitude: Double
let longitude: Double
let direction: Int
let speed: Int
}
struct BusProperties: Decodable {
let routeShortName: String
let blockID: String
let isTripper: Bool
let patternName: String
let tripStartTime: String
let lastStopName: String
let stopCode: Int
let isBusAtStop: Bool
let isTimePoint: Bool
let latestRSAEvent: String
let totalCount: Int
let percentOfCapacity: Int
}
let decoder = XMLDecoder()
decoder.keyDecodingStrategy = .convertFromCapitalized
let vehicle = try decoder.decode(VehicleProperties.self, from: vehicle1)
let bus = try decoder.decode(BusProperties.self, from: vehicle1)
- Decode to multiple structs with a parent struct:
struct VehicleProperties: Decodable {
let agencyVehicleName: String
let latestEvent: String
let latitude: Double
let longitude: Double
let direction: Int
let speed: Int
}
struct BusProperties: Decodable {
let routeShortName: String
let blockID: String
let isTripper: Bool
let patternName: String
let tripStartTime: String
let lastStopName: String
let stopCode: Int
let isBusAtStop: Bool
let isTimePoint: Bool
let latestRSAEvent: String
let totalCount: Int
let percentOfCapacity: Int
}
struct AllProperties: Decodable {
let vehicle: VehicleProperties
let bus: BusProperties?
init(from decoder: Decoder) throws {
let vehicleContainer = try decoder.singleValueContainer()
let busContainer = vehicleContainer
vehicle = try vehicleContainer.decode(VehicleProperties.self)
bus = try? busContainer.decode(BusProperties.self)
}
}
let decoder = XMLDecoder()
decoder.keyDecodingStrategy = .convertFromCapitalized
let properties1 = try decoder.decode(AllProperties.self, from: vehicle1)
let properties2 = try decoder.decode(AllProperties.self, from: vehicle2)
Hi @mhs2342, I would like to add more sample code to the README of XMLCoder, would you mind if I take your XML snippet and use it that way? Thank you!
@MaxDesiatov Sure! Sorry for the delay, I haven't had a chance to dive into this yet. You can find the api where similar requests happen here
Hi @mhs2342! I know it's been a while, were you able to have a look and can the issue be resolved at this point?