@Exclude属性包装器用于Swift中的Firebase编码器/解码器

huangapple go评论70阅读模式
英文:

@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转义字符(如&quot;)。如果您需要进一步的翻译或有其他问题,请告诉我。

英文:

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&lt;Wrapped&gt; {
    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&lt;Wrapped&gt;` func in `KeyedEncodingContainer`
    }
}

extension CodableExcluded: Decodable {
    public init(from decoder: Decoder) throws {
        self.wrappedValue = nil
    }
}

extension KeyedDecodingContainer {
    public func decode&lt;Wrapped&gt;(_ type: CodableExcluded&lt;Wrapped&gt;.Type, forKey key: Self.Key) throws -&gt; CodableExcluded&lt;Wrapped&gt; {
        CodableExcluded(wrappedValue: nil)
    }
}

extension KeyedEncodingContainer {
    public mutating func encode&lt;Wrapped&gt;(_ value: CodableExcluded&lt;Wrapped&gt;, forKey key: KeyedEncodingContainer&lt;K&gt;.Key) throws {
        // Do nothing.
    }
}

Usage

struct Test: Codable {
    var codedString = &quot;This will be included during encoding and decoded back.&quot;
    @CodableExcluded var nonCodedString: String? = &quot;This will NOT be included when encodig and assigned `nil` when decoded from decoded.&quot;
}

let data = try JSONEncoder().encode(Test())
print(String(data: data, encoding: .utf8) ?? &quot;&quot;)

let obj = try JSONDecoder().decode(Test.self, from: data)
print(obj)

huangapple
  • 本文由 发表于 2023年3月9日 21:04:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/75685020.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定