SQLite.swift
SQLite.swift copied to clipboard
SQLiteDecoder & Codable with NULL Values
Are null values actually supported by your SQLiteDecoder?
Build Information
CocoaPods, SQLite.swift version 0.12.2 iOS 13.4, XCode 11.4.1
General guidelines
I just tried to read an array of my table's contents, but then I got an exception.
In Coding.swift:235 I get an error by QueryError.unexpectedNullValue.
Are null values within Codables supported?
No. You need to handle it yourself.
I came up with this if you wanna try :
Put this somewhere
protocol SQLiteCompatibleType: Encodable {}
extension Int: SQLiteCompatibleType {}
extension String: SQLiteCompatibleType {}
extension Bool: SQLiteCompatibleType {}
extension Double: SQLiteCompatibleType {}
extension Float: SQLiteCompatibleType {}
extension Data: SQLiteCompatibleType {}
extension KeyedEncodingContainerProtocol {
mutating func encodeNullable<T>(_ value: T?, forKey key: Key) throws where T: SQLiteCompatibleType {
if let unwrappedValue = value {
if let int = unwrappedValue as? Int {
try self.encode(int, forKey: key)
} else if let double = unwrappedValue as? Double {
try self.encode(double, forKey: key)
} else if let float = unwrappedValue as? Float {
try self.encode(float, forKey: key)
} else if let bool = unwrappedValue as? Bool {
try self.encode(bool, forKey: key)
} else if let data = unwrappedValue as? Data {
try self.encode(data, forKey: key)
} else if let string = unwrappedValue as? String {
try self.encode(string, forKey: key)
} else {
try self.encode(unwrappedValue, forKey: key)
}
} else {
try self.encodeNil(forKey: key)
}
}
}
and change the following func in Coding.swift :
func encode<T>(_ value: T, forKey key: Key) throws where T: Swift.Encodable {
if let data = value as? Data {
self.encoder.setters.append(Expression(key.stringValue) <- data)
} else if let string = value as? String {
self.encoder.setters.append(Expression(key.stringValue) <- string)
} else {
let encoded = try JSONEncoder().encode(value)
let string = String(data: encoded, encoding: .utf8)
self.encoder.setters.append(Expression(key.stringValue) <- string)
}
}
And then in func encode(to encoder: Encoder) throws
in your object class definition, use encodeNullable
and in required convenience init(from decoder: Decoder) throws
use decodeIfPresent
for optional values
Hope it will help :)
Thanks for your support, will try that.
@TenMaKo I have added SQLIte.swift using SPM (Swift Package Manager). How do I update Coding.swift file code ?
@TenMaKo I have added SQLIte.swift using SPM (Swift Package Manager). How do I update Coding.swift file code ?
I don’t use SPM so I’m not sure about this but I think you can’t cause SPM import pre-built packages. Maybe you will need to fork this repo, modify the file and then import the lib from your own repo :/ Again, it’s just a guess.
@TenMaKo Don't you think you should create a PR and then merge this fix into master. More people are facing the issue..
@TenMaKo Don't you think you should create a PR and then merge this fix into master. More people are facing the issue..
No sorry cause this is just a workaround. A clean fix should make standard Codable usage for this lib handle optionals correctly.
@TenMaKo got it thanks for clarification...
@TenMaKo Feel free to open a PR to fix this issue