Skip to content

Instantly share code, notes, and snippets.

@kkebo
Created June 13, 2020 17:03
Show Gist options
  • Save kkebo/cae882ebceeaeba943bc4fc3ede52859 to your computer and use it in GitHub Desktop.
Save kkebo/cae882ebceeaeba943bc4fc3ede52859 to your computer and use it in GitHub Desktop.
XMLCoder experiments
import XMLCoder
struct Root: Equatable {
let elements: [Choice]
let name: String
let description: String?
}
extension Root: Codable {
enum CodingKeys: String, CodingKey {
case elements = ""
case name, description
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(self.elements, forKey: .elements)
try container.encode(self.name, forKey: .name)
try container.encodeIfPresent(self.description, forKey: .description)
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.name = try container.decode(String.self, forKey: .name)
self.description = try container.decodeIfPresent(String.self, forKey: .description)
var unkeyedContainer = try decoder.unkeyedContainer()
var elements = [Choice]()
while !unkeyedContainer.isAtEnd {
elements.append(try unkeyedContainer.decode(Choice.self))
}
self.elements = elements
}
}
extension Root: DynamicNodeEncoding {
static func nodeEncoding(for key: CodingKey) -> XMLEncoder.NodeEncoding {
switch key {
case CodingKeys.name, CodingKeys.description:
return .attribute
default:
return .element
}
}
}
enum Choice: Equatable {
case foo(Foo)
case bar(Bar)
}
extension Choice: Codable {
enum CodingKeys: String, XMLChoiceCodingKey {
case foo, bar
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
switch self {
case let .foo(foo):
try container.encode(foo, forKey: .foo)
case let .bar(bar):
try container.encode(bar, forKey: .bar)
}
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
do {
self = .foo(try container.decode(Foo.self, forKey: .foo))
} catch {
self = .bar(try container.decode(Bar.self, forKey: .bar))
}
}
}
struct Foo: Equatable {
let name: String
}
extension Foo: Codable {}
extension Foo: DynamicNodeEncoding {
static func nodeEncoding(for key: CodingKey) -> XMLEncoder.NodeEncoding {
.attribute
}
}
struct Bar: Equatable {
let name: String
}
extension Bar: Codable {}
extension Bar: DynamicNodeEncoding {
static func nodeEncoding(for key: CodingKey) -> XMLEncoder.NodeEncoding {
.attribute
}
}
let original = Root(
elements: [
.foo(Foo(name: "foo1")),
.foo(Foo(name: "foo2")),
.bar(Bar(name: "bar1")),
],
name: "root",
description: nil
)
let encoded = try XMLEncoder().encode(original)
let decoded = try XMLDecoder().decode(Root.self, from: encoded)
original == decoded
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment