SQLite.swift icon indicating copy to clipboard operation
SQLite.swift copied to clipboard

SQLiteDecoder & Codable with NULL Values

Open Sevyls opened this issue 4 years ago • 8 comments

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?

Sevyls avatar Apr 24 '20 16:04 Sevyls

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 :)

TenMaKo avatar Apr 27 '20 14:04 TenMaKo

Thanks for your support, will try that.

Sevyls avatar Apr 27 '20 14:04 Sevyls

@TenMaKo I have added SQLIte.swift using SPM (Swift Package Manager). How do I update Coding.swift file code ?

rahulvyas avatar Apr 28 '20 05:04 rahulvyas

@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 avatar Apr 29 '20 07:04 TenMaKo

@TenMaKo Don't you think you should create a PR and then merge this fix into master. More people are facing the issue..

rahulvyas avatar Apr 29 '20 07:04 rahulvyas

@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 avatar Apr 29 '20 09:04 TenMaKo

@TenMaKo got it thanks for clarification...

rahulvyas avatar Apr 29 '20 09:04 rahulvyas

@TenMaKo Feel free to open a PR to fix this issue

nathanfallet avatar Aug 22 '21 20:08 nathanfallet