Skip to content

Instantly share code, notes, and snippets.

@emrepun
Created February 3, 2020 20:31
Show Gist options
  • Save emrepun/0f2d76ffdedce26fc2dec95dfe037347 to your computer and use it in GitHub Desktop.
Save emrepun/0f2d76ffdedce26fc2dec95dfe037347 to your computer and use it in GitHub Desktop.
Parse json item array (consists of different items) with enums & associated values
import Foundation
struct GeometricShapes: Decodable {
let items: [Object]
}
enum Object: Decodable {
case square(Square)
case sphere(Sphere)
case cylinder(Cylinder)
case unknown
enum CodingKeys: String, CodingKey {
case type
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
guard let type = try? container.decode(ObjectType.self, forKey: .type) else {
self = .unknown
return
}
let objectContainer = try decoder.singleValueContainer()
switch type {
case .square:
let square = try objectContainer.decode(Square.self)
self = .square(square)
case .sphere:
let sphere = try objectContainer.decode(Sphere.self)
self = .sphere(sphere)
case .cylinder:
let cylinder = try objectContainer.decode(Cylinder.self)
self = .cylinder(cylinder)
case .unknown:
self = .unknown
}
}
}
enum ObjectType: String, Decodable {
case square
case sphere
case cylinder
case unknown
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
let type = try container.decode(String.self)
self = ObjectType(rawValue: type) ?? .unknown
}
}
struct Square: Decodable {
let sideLength: Int
enum CodingKeys: String, CodingKey {
case sideLength = "side_length"
}
}
struct Sphere: Decodable {
let diameter: Int
}
struct Cylinder: Decodable {
let diameter: Int
let height: Int
}
let JSON = """
{
"items": [
{
"type": "square",
"side_length": 12
},
{
"type": "sphere",
"diameter": 4
},
{
"type": "cylinder",
"diameter": 4,
"height": 10
},
{
"type": "lalala",
"unknown_key": 0
}
]
}
""".data(using: .utf8)!
let decoder = JSONDecoder()
let geometricObjects = try decoder.decode(GeometricShapes.self, from: JSON)
let items = geometricObjects.items
// Here we just parse and print some values of the models.
// This is how you can parse with a wrapper enum with associated value.
items.forEach({
switch $0 {
case .cylinder(let cylinder):
print("Diameter of cylinder is: \(cylinder.diameter)")
print("Height of cylinder is: \(cylinder.height)")
case .sphere(let sphere):
print("Diameter of sphere is: \(sphere.diameter)")
case .square(let square):
print("Side length of square is: \(square.sideLength)")
case .unknown:
print("We have an unknown type.")
}
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment