I am wondering if there is a different approach I could take here aside from the nested do { try } catch { do { try } catch { do { try } catch { ... }}}}}}
approach I am currently using.
Similarly, any comments or suggestions on the switch self { ... }
block would be appreciated.
UniversalPayload
is to encode and decode a JSON payload object which contains three properties op: Int
, t: String?
, s: Int?
, which have a known type and structure, and one property d: JSONAble?
which is known to conform to JSON but has an unknown structure otherwise.
Will someone please suggest improvements to the following code?
struct UniversalPayload: Codable {
typealias GenericPayloadData = [String: PayloadDatum?]
var op: Int
var t: String?
var s: Int?
var d: GenericPayloadData?
enum PayloadDatum: Codable {
case array([PayloadDatum])
case bool(Bool)
case int(Int)
case null(Bool)
case object(GenericPayloadData)
case string(String)
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
var value: PayloadDatum?
// Pyramid of do do do do doooom
do { value = try .bool(container.decode(Bool.self)) } catch {
do { value = try .int(container.decode(Int.self)) } catch {
do { value = try .string(container.decode(String.self)) } catch {
do { value = try .array(container.decode([PayloadDatum].self)) } catch {
do { value = try .object(container.decode(GenericPayloadData.self)) } catch {
value = .null(container.decodeNil())
} // catch .object
} // catch .array
} // catch .string
} // catch .int
} // catch .bool
self = value!
} // init
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case .array(let arrayValue):
try? container.encode(arrayValue)
case .bool(let boolValue):
try? container.encode(boolValue)
case .int(let intValue):
try? container.encode(intValue)
case .object(let objectValue):
try? container.encode(objectValue)
case .string(let stringValue):
try? container.encode(stringValue)
case .null(let nullValue):
if nullValue {
try? container.encodeNil()
}
else {
let context = EncodingError.Context(codingPath: encoder.codingPath,
debugDescription: "Unknown Type")
throw EncodingError.invalidValue(self, context )
} // else
} // switch
} // encode
} // PayloadDatum
} // UniversalPayload