Home > Software design >  Issue with Enum values with Space | Swift
Issue with Enum values with Space | Swift

Time:08-24

Essentially I am decoding a JSON object with keys that could only be a few different values.

 struct People: Decodable {
        var name: String
        var grade: String
        var code: PersonID
        
        enum PersonCodes: String, Decodable {
            case In_Transit = "0",
                 Accepted = "1",
                 Exception = "2",
                 Delivered = "3"
        }
}

The codes values in the JSON are numbers presented as Strings like "0", "1", "2" etc.. Each code has a meaning like In_Transit, Hired, Ready, All Set .. how can codes be outputed with spaces if enums does not allow spaces (I need to replace the _ with space).

Example of JSON:

{
"name" : "Jake",
"grade" : "A Grade"
"code" : "0"
}

Need for code 0 to be read as "In Transit"

CodePudding user response:

You can add CustomStringConvertible conformance and then you can use

People.PersonCodes.in_Transit.description

Your enum would look something like.

struct People: Decodable {
    var name: String
    var grade: String
    var code: PersonCodes
    
    enum PersonCodes: String,  CustomStringConvertible, Decodable {
        //Variables should be lowercased
        case in_Transit = "0",
             accepted = "1",
             exception = "2",
             delivered = "3"
        ///Textual representation for the value
        var description: String{
            switch self {
            case .in_Transit:
                return "In Transit"
            case .accepted:
                return "Accepted"
            case .exception:
                return "Exception"
            case .delivered:
                return "Delivered"
            }
        }
        
    }
}

CodePudding user response:

you could try this approach (works for me):

struct People: Decodable {
    var name: String
    var grade: String
    var code: PersonCodes
    
    enum CodingKeys: String, CodingKey {
        case name, grade, code
    }
    
    enum PersonCodes: String, Decodable {
        case In_Transit = "0",
             Accepted = "1",
             Exception = "2",
             Delivered = "3"
    }
    
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        name = try container.decode(String.self, forKey: .name)
        grade = try container.decode(String.self, forKey: .grade)
        let stringCode = try container.decode(String.self, forKey: .code)
        if let dasCode = PersonCodes(rawValue: stringCode) {
            code = dasCode
        } else {
            code = PersonCodes.In_Transit  // <-- todo, pick a default 
        }
    }
    
}

struct ContentView: View {
    var body: some View {
        Text("testing")
            .onAppear {
                let json = """
    {
    "name" : "Jake",
    "grade" : "A Grade",
    "code" : "1"
    }
    """
                let data = json.data(using: .utf8)!
                do {
                    let decoded = try JSONDecoder().decode(People.self, from: data)
                    print(decoded)
                    print(decoded.code)
                    print(decoded.code.rawValue)
                } catch {
                    print("\(error)")
                }
            }
    }
    
}

You could also use this, if you want a string description of the code (which is a String not an Int in the json data):

struct People: Decodable {
    var name: String
    var grade: String
    var code: String
    
    enum CodingKeys: String, CodingKey {
        case name, grade, code
    }
    
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        name = try container.decode(String.self, forKey: .name)
        grade = try container.decode(String.self, forKey: .grade)
        let stringCode = try container.decode(String.self, forKey: .code)
        switch stringCode {
        case "0": code = "In Transit"
        case "1": code = "Accepted"
        case "2": code = "Exception"
        case "3": code = "Delivered"
        default: code = "Unknown"  // <-- todo default
        }
    }
    
}
  • Related