# Reducing Array\<OptionSet\> to OptionSet

**URL:** <https://forums.swift.org/t/reducing-array-optionset-to-optionset/4438>\
**Category:** Using Swift\
**Created:** [November 4, 2016, 1:09am UTC](https://forums.swift.org/t/reducing-array-optionset-to-optionset/4438 "2016-11-04T01:09:57Z")\
**Posts on this page:** 1\
**Showing post:** 10

<div class="post-metadata">

**Author:** ![rauhul](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/rauhul/32/35207_2.png) [@rauhul](https://forums.swift.org/u/rauhul)\
**Post date:** [January 25, 2019, 4:10am UTC](https://forums.swift.org/t/reducing-array-optionset-to-optionset/4438/10 "2019-01-25T04:10:00Z")

</div>

Sorry to revive an old thread!

I'm running into a very similar issue and I'm not sure if there's a cleaner way to implement encoding/decoding. I have a REST api that returns options as json array, ex: `"["OptionB", "OptionC"]"` and I would like to form an OptionSet from it as well as re-encode to that format.

I have the following implementation that works, but requires a lot of manual updating if the supported options changes. Is there a better way to write this, or perhaps use `Mirror` to get the behavior I'd like?

(note: I'm very unfamiliar with swift's reflection apis. Also, please let me know if this is off-topic; I can make a new thread if that would be better.)

```swift
struct ExampleOptions: OptionSet, Codable {
    let rawValue: Int

    static let optionA = ExampleOptions(rawValue: 1 << 0)
    static let optionB = ExampleOptions(rawValue: 1 << 1)
    static let optionC = ExampleOptions(rawValue: 1 << 2)

    init(rawValue: Int) {
        self.rawValue = rawValue
    }

    init(from decoder: Decoder) throws {
        var container = try decoder.unkeyedContainer()
        var options = [ExampleOptions]()
        while !container.isAtEnd {
            let string = try container.decode(String.self)
            let option = try ExampleOptions(string: string)
            options.append(option)
        }
        let null = ExampleOptions(rawValue: 0)
        self = options.reduce(null) { return $0.union($1) }
    }

    init(string: String) throws {
        switch string {
        case "OptionA": self = .optionA
        case "OptionB": self = .optionB
        case "OptionC": self = .optionC
        default: throw NSError(domain: "ExampleOptions", code: 0, userInfo: nil) // make this more descriptive
        }
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.unkeyedContainer()
        if contains(.optionA) { try container.encode("OptionA") }
        if contains(.optionB) { try container.encode("OptionB") }
        if contains(.optionC) { try container.encode("OptionC") }
    }
}

```

---

_[View the full topic](https://forums.swift.org/t/reducing-array-optionset-to-optionset/4438)._
