英文:
@Exclude property wrapper for Firebase Encoder/Decoder in Swift
问题
Firebase Android库具有"Exclude"注释,允许在将对象保存到数据库和从数据库检索对象时忽略属性。
Swift中的FirebaseFirestoreSwift
库是否有类似的属性包装器?
就我所见,Swift库中的DocumentId注释具有等效的属性包装器。
无论如何,在Swift中,如何最佳地排除Codable
对象中的属性?
英文:
Firebase Android library has Exclude annotation which allows to ignore a property when saving/retrieving object to and from database.
Is there a similar property wrapper for Swift FirebaseFirestoreSwift
library?
As far as I can see DocumentId annotation has equivalent property wrapper in Swift library.
What is the best way to exclude property from database in Codable
object in Swift anyway?
答案1
得分: 3
使用CodingKeys
是调整Codable映射的默认机制。如果您对Codable的工作原理有兴趣,请查看这本出色的书籍:《Flight School指南Swift Codable》 和这篇Hacking with Swift文章:Codable备忘单 - Hacking with Swift。
Firebase文档中有关使用Codable与Firestore的全面指南:使用Swift Codable映射Cloud Firestore数据,其中介绍了在此部分中如何自定义映射:
在相应的CodingKeys枚举上未列出的任何属性都将在映射过程中被忽略。如果我们明确希望排除某些属性不被映射,这实际上可以很方便。
如果您在本指南中找不到需要的信息,请告诉我们,以便我们添加。
英文:
Using CodingKeys
is the default mechanism to fine-tune Codable's mapping. If you're interested in how Codable works in general, check out this excellent book: Flight School Guide to Swift Codable and this Hacking with Swift article: Codable cheat sheet – Hacking with Swift.
The Firebase documentation has a comprehensive guide for using Codable with Firestore: Map Cloud Firestore data with Swift Codable, which talks about customising the mapping in this section:
> Any property that is not listed as a case on the respective CodingKeys enum will be ignored during the mapping process. This can actually be convenient if we specifically want to exclude some of the properties from being mapped.
If you find anything missing in this guide, please let us know so we can add it.
答案2
得分: 0
以下是代码部分的翻译:
我已经创建了这样的包装器。它使代码更加简洁。它确实处理了 `Codable`,并且应该与 Firebase Coder 一样好地使用,就像与任何其他编码器(例如 JSONEncoder/Decoder)一样。让我谦虚地介绍
## @CodableExcluded ##
import Foundation
@propertyWrapper
public struct CodableExcluded<Wrapped> {
public var wrappedValue: Wrapped?
public init(wrappedValue: Wrapped?) {
self.wrappedValue = wrappedValue
}
}
extension CodableExcluded: Encodable {
public func encode(to encoder: Encoder) throws {
// 什么都不做。实际上,由于 `KeyedEncodingContainer` 中的空的 `encode<Wrapped>` 函数,这从未被调用。
}
}
extension CodableExcluded: Decodable {
public init(from decoder: Decoder) throws {
self.wrappedValue = nil
}
}
extension KeyedDecodingContainer {
public func decode<Wrapped>(_ type: CodableExcluded<Wrapped>.Type, forKey key: Self.Key) throws -> CodableExcluded<Wrapped> {
CodableExcluded(wrappedValue: nil)
}
}
extension KeyedEncodingContainer {
public mutating func encode<Wrapped>(_ value: CodableExcluded<Wrapped>, forKey key: KeyedEncodingContainer<K>.Key) throws {
// 什么都不做。
}
}
## 用法 ##
struct Test: Codable {
var codedString = "This will be included during encoding and decoded back."
@CodableExcluded var nonCodedString: String? = "This will NOT be included when encoding and assigned `nil` when decoded from decoded."
}
let data = try JSONEncoder().encode(Test())
print(String(data: data, encoding: .utf8) ?? "")
let obj = try JSONDecoder().decode(Test.self, from: data)
print(obj)
请注意,我已经翻译了代码部分,不包括代码中的HTML转义字符(如"
)。如果您需要进一步的翻译或有其他问题,请告诉我。
英文:
I've created such wrapper. It makes code more concise. It indeed deals with Codable
, and should work fine with Firebase Coder as good as with any other one (such as JSONEncoder/Decoder). Let me modestly present
@CodableExcluded
import Foundation
@propertyWrapper
public struct CodableExcluded<Wrapped> {
public var wrappedValue: Wrapped?
public init(wrappedValue: Wrapped?) {
self.wrappedValue = wrappedValue
}
}
extension CodableExcluded: Encodable {
public func encode(to encoder: Encoder) throws {
// Do nothing. Actually this is never called due to empty `encode<Wrapped>` func in `KeyedEncodingContainer`
}
}
extension CodableExcluded: Decodable {
public init(from decoder: Decoder) throws {
self.wrappedValue = nil
}
}
extension KeyedDecodingContainer {
public func decode<Wrapped>(_ type: CodableExcluded<Wrapped>.Type, forKey key: Self.Key) throws -> CodableExcluded<Wrapped> {
CodableExcluded(wrappedValue: nil)
}
}
extension KeyedEncodingContainer {
public mutating func encode<Wrapped>(_ value: CodableExcluded<Wrapped>, forKey key: KeyedEncodingContainer<K>.Key) throws {
// Do nothing.
}
}
Usage
struct Test: Codable {
var codedString = "This will be included during encoding and decoded back."
@CodableExcluded var nonCodedString: String? = "This will NOT be included when encodig and assigned `nil` when decoded from decoded."
}
let data = try JSONEncoder().encode(Test())
print(String(data: data, encoding: .utf8) ?? "")
let obj = try JSONDecoder().decode(Test.self, from: data)
print(obj)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论