简体   繁体   中英

Handling missing properties when deserializing xml using SWXMLHash

I've been following the examples at SWXMLHash to deserialize an XML file. It is working quite well, but I am not sure how to handle cases when the XML input is incomplete:

For example, suppose the XML input is this:

<shippingInfo>
            <shippingServiceCost currencyId="USD">0.0</shippingServiceCost>
            <shippingType>Free</shippingType>
            <shipToLocations>US</shipToLocations>
            <expeditedShipping>true</expeditedShipping>
            <oneDayShippingAvailable>false</oneDayShippingAvailable>
            <handlingTime>1</handlingTime>
</shippingInfo>

To deserialize this XML, I create the following struct that is an XMLIndexerDeserializable

import SWXMLHash

struct ShippingInfo: XMLIndexerDeserializable
{
    let currencyId: String
    let shippingServiceCost: Double
    let shippingType: String
    let shipToLocations: String
    let expeditedShipping: Bool
    let oneDayShippingAvailable: Bool
    let handlingTime: Int

    static func deserialize(_ node: XMLIndexer) throws -> ShippingInfo 
    {
        return try ShippingInfo(
            currencyId: node["shippingServiceCost"].value(ofAttribute: "currencyId"),
            shippingServiceCost: node["shippingServiceCost"].value(),
            shippingType: node["shippingType"].value(),
            shipToLocations: node["shipToLocations"].value(),
            expeditedShipping: node["expeditedShipping"].value(),
            oneDayShippingAvailable: node["oneDayShippingAvailable"].value(),
            handlingTime: node["handlingTime"].value()
        )
    }
}

The code above works, until the shippingInfo XML misses an element, like so:

<shippingInfo>
            <shippingServiceCost currencyId="USD">0.0</shippingServiceCost>
            <shippingType>Free</shippingType>
            <shipToLocations>Worldwide</shipToLocations>
            <expeditedShipping>false</expeditedShipping>
            <oneDayShippingAvailable>false</oneDayShippingAvailable>
</shippingInfo>

The 2nd XML above is missing the property "handlingTime" . Running the deserialization code above would throw an exception at node["handlingTime"].value()

One approach to fix this problem is to try to catch the exception whenever we access the XMLIndexer's key, and pass in a default value to the property if the exception is thrown which means the key isn't there. I don't think this is best approach though.

What is the best approach to deserialize XML when the XML is missing properties?

Change the declaration of your handlingTime property from Int to Int? , like so:

let handlingTime: Int?

It needs to be nullable so that the deserialization can support a value that doesn't exist.

Hope this helps!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM