skip to Main Content

Requiring some assistance for acquiring a value in json. I want to access the radioButton object and access the description value (e.g Other Products from Competitors have better product) to assign to tileView.title as shown below:

 for viewContent in viewModel.contents {
            switch viewContent {
            case let .radioButtonGroup(radioButtonGroupModel):
                for i in 0..<radioButtonGroupModel.options.count {
                    let tileView = TileRadio()
                    tileView.title = radioButtonGroupModel.options...

Printing this print(radioButtonGroupModel.options[i]) gets:

radioButton(RadioButtonModel(description: "Other Products from Competitors have better product", identifier: "competitorReason"))

Here’s the codebase for json decoder:

enum ComponentModel: Decodable {

    case radioButtonGroup(RadioButtonGroupModel)
    case radioButton(RadioButtonModel)
    case emptyComponent

    enum CodingKeys: String, CodingKey {
        case radioButtonGroup
        case radioButton
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        do {
            switch container.allKeys.first {

            case .radioButtonGroup:
                let value = try container.decode(RadioButtonGroupModel.self, forKey: .radioButtonGroup)
                self = .radioButtonGroup(value)
            case .radioButton:
                let value = try container.decode(RadioButtonModel.self, forKey: .radioButton)
                self = .radioButton(value)
            case .none:
                self = .emptyComponent
            }
        } catch {
            self = .emptyComponent
        }
    }
}

struct RadioButtonGroupModel: Decodable {
    let options: [ComponentModel]
}

struct RadioButtonModel: Decodable {
    let description: String
    let identifier: String
}

Here’s the partial JSON file:

"closureReasons": {
        "pageTitle": "Close account",
        "content": [
 
            {
                "heading": {
                    "title": "Why are you closing this account?"
                }
            },
            {
                "spacing": ".spacing3x"
            },
            {
                "radioButtonGroup": {
                    "options": [
                        {
                            "radioButton": {
                                "identifier": "competitorReason",
                                "description": "Other Products from Competitors have better product"
                            }
                        },
                        {
                            "radioButton": {
                                "identifier": "betterReason",
                                "description": "I found a better product"
                            }
                        },

Any idea on how to retrieve radioButton attributes? Thank you kindly for your help

2

Answers


  1. for loops can also pattern match with case let:

    for case let .radioButton(radioButtonModel) in radioButtonGroupModel.options {
        print(radioButtonModel.description)
    }
    

    This loops through all the ComponentModels in options that are .radioButtons.

    Or if you need the index for some reason:

    for case let (i, .radioButton(radioButtonModel)) in radioButtonGroupModel.options.enumerated() {
        print(i, radioButtonModel.description)
    }
    

    That said, if RadioButtonGroupModel.options can only contain the .radioButton case, I’d suggest changing its type to [RadioButtonModel] instead, and add some custom decoding logic to decode it:

    struct RadioButtonGroupModel: Decodable {
        let options: [RadioButtonModel]
        
        enum OptionsCodingKey: String, CodingKey {
            case options
        }
        
        
        enum RadioButtonCodingKey: String, CodingKey {
            case radioButton
        }
        
        init(from decoder: Decoder) throws {
            var container = try decoder.container(keyedBy: OptionsCodingKey.self)
            var arrayContainer = try container.nestedUnkeyedContainer(forKey: .options)
            var options = [RadioButtonModel]()
            while !arrayContainer.isAtEnd {
                var radioButtonContainer = try arrayContainer.nestedContainer(keyedBy: RadioButtonCodingKey.self)
                if let model = radioButtonContainer.decodeIfPresent(RadioButtonModel.self, forKey: .radioButton) {
                    options.append(model)
                }
            }
            self.options = options
            
        }
    }
    
    Login or Signup to reply.
  2. First you’ll need to filter the objects so that they all share the same pattern is bound for each of the enumerated options.

    i.e.

    switch viewContent.filter {if case ComponentModel. emptyComponent = $0 {return false}; return true} {
    

    or you could use if let like so:

    if case ComponentModel.radioButtonGroup(let RBGMContent) = radioButtonGroupModel.options[i] {
        print(GMContent)
    } else if case ComponentModel.radioButtonGroup(let RBMContent) = radioButtonGroupModel.options[i] {
    } else { 
        //this is ComponentModel.emptyComponent
    }
    

    That being said I would probably use a struct instead of an enum for this, but that’s completely up to you.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search