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
}
}
}