Swift-Kuery-ORM
Swift-Kuery-ORM copied to clipboard
RawRepresentable not supported in SQLite
Context and Description
As I mentioned in Issue #42, I get errors encoding and decoding Enums which are RawRepresentable
& Codable
.
I have a tentative solution but at the moment is is per RawType
, so would likely be user-specific.
Maybe this could be added to your codebase as an example or to your documentation.
Here is the solution for Int
based enum
, String
etc. is equally trivial.
extension KeyedEncodingContainer {
public mutating func encodeIfPresent<T>(_ value: T?, forKey key: K) throws where T : Encodable & RawRepresentable, T.RawValue == Int {
try encodeIfPresent(value?.rawValue, forKey: key)
}
}
extension KeyedDecodingContainer {
public func decodeIfPresent<T>(_ type: T.Type, forKey key: K) throws -> T? where T : Decodable & RawRepresentable, T.RawValue == Int {
if let value = try decodeIfPresent(Int.self, forKey: key) {
return T.init(rawValue: value)
}
return nil
}
}
Environment Details
Information about your OS, Swift version and Xcode version if on macOS. MacOS 10.13.4 Xcode 9.4 Kitura 2.4.1 SwiftKuery 1.3.1 SwiftKueryORM 0.1.1 SwiftKuerySQLite 1.0.0
Steps to Reproduce
Model struct contains enum :
public struct Bookmark:Codable, Equatable {
...
public var created: Status? // the read status
...
}
public enum Status:Int, Codable {
case nought = 0 // no special status
case unread // the user would like to see this highlighted as being in their reading list
case read // this was in the user's reading list but now they are finished
}
Hey @jeremyquinn, this is something we should definitely support! Maybe we could have a protocol that the enum has to implement so it can be used in the ORM? Could you open a PR with your prototype?
Hi @EnriqueL8, glad to know you are interested.
The only way I have managed to make this work so far, is to be specific about the type of the RawValue
and use a global extension.
My guess is that an implementation for Int
and String
RawValue
will cover 90% of use cases.
Enums can already be made Codable
and were already supported by the JSONDecoder
. They just were not supported by your DatabaseDecoder
/Encoder
.
I want to test this extension has no effect on normal Codable
usage.
I want to see if it can be added as an extension private to this module only.
I plan to add the support for String
Added PR #46
Sorry, it looks like my last PR got mixed in ...
Is there still a plan to include this in the near future? I'm running into the same issues.
Seems it is still broken... I realized that somehow DatabaseEncoder only supports types that do not need any mapping/encoding:
public mutating func encode<T: Encodable>(_ value: T, forKey key: Key) throws {
if let dataValue = value as? Data {
} else {
encoder.values[key.stringValue] = value
}
when value is an enum type, then values
only contains the naked enum value, rather than storing the mapped value (I use a property wrapper that encodes the enums into their rawValue
. the wrapper's encoder is invoked when using JSONEncoder, but never invoked when using DatabaseEncoder.
fileprivate class _DatabaseEncoder: Encoder {
public var values: [String: Any] = [:]
}