Skip to content

Instantly share code, notes, and snippets.

@Pretz
Created February 16, 2022 05:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Pretz/e608759f38087892bd02102d22fb57a3 to your computer and use it in GitHub Desktop.
Save Pretz/e608759f38087892bd02102d22fb57a3 to your computer and use it in GitHub Desktop.
StringCodable
struct User: Codable, Equatable {
@StringDecodable
var identifier: Int
@StringCodable
var anotherID: UInt64
}
let user = User(identifier: 100, anotherID: 1030402030)
user.anotherID
let val = try JSONEncoder().encode(user)
String(bytes: val, encoding: .utf8)
let str1 = """
{ "anotherID": 1030402030,
"identifier": 100 }
"""
let user1 = try JSONDecoder().decode(User.self, from: Data(str1.utf8))
let str2 = """
{ "anotherID": "1030402030",
"identifier": "100" }
"""
let user2 = try JSONDecoder().decode(User.self, from: Data(str2.utf8))
user1 == user2 // true
// Prints {"anotherID":"1030402030","identifier":100}
print(String(decoding: try JSONEncoder().encode(user), as: UTF8.self))
@propertyWrapper
public struct StringDecodable<T: Decodable & LosslessStringConvertible>: Decodable {
public var wrappedValue: T
public init(wrappedValue: T) { self.wrappedValue = wrappedValue }
public init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
let convertedValue: T
do {
convertedValue = try container.decode(T.self)
} catch {
let stringInteger = try container.decode(String.self)
// Lazy. Better to throw a more specific error
guard let value = T(stringInteger) else { throw error }
convertedValue = value
}
self.wrappedValue = convertedValue
}
}
extension StringDecodable: Encodable where T: Encodable {
public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try container.encode(wrappedValue)
}
}
@propertyWrapper
public struct StringCodable<T: Decodable & LosslessStringConvertible>: Codable {
public var wrappedValue: T
public init(wrappedValue: T) { self.wrappedValue = wrappedValue }
public init(from decoder: Decoder) throws {
wrappedValue = try StringDecodable(from: decoder).wrappedValue
}
public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try container.encode(wrappedValue.description)
}
}
extension StringDecodable: Equatable where T: Equatable { }
extension StringDecodable: Hashable where T: Hashable { }
extension StringCodable: Equatable where T: Equatable { }
extension StringCodable: Hashable where T: Hashable { }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment