![](/img/trans.png)
[英]Python attrs/cattrs serializing a dict using frozen attrs classes as the dict keys
[英]Using cattrs / attrs where attr name does not match keys to create an object
我正在考慮從輸入所有類的完全手動過程轉移到 cattrs / attrs,但需要一些幫助來理解如何實現以下目標。
這是一個示例,但返回的數據會有所不同,有時不會填充所有字段。
data = {
"data": [
{
"broadcaster_id": "123",
"broadcaster_login": "Sam",
"language": "en",
"subscriber_id": "1234",
"subscriber_login": "Dave",
"moderator_id": "12345",
"moderator_login": "Tom",
"delay": "0",
"title": "Weekend Events"
}
]
}
@attrs.define
class PartialUser:
id: int
login: str
@attrs.define
class Info:
language: str
title: str
delay: int
broadcaster: PartialUser
subscriber: PartialUser
moderator: PartialUser
因此,我了解您將如何構建它,並且它與預期的 1:1 映射完美配合,但是您將如何動態創建 PartialUser 對象,因為名稱與來自 API 的 JSON 響應不同?
instance = cattrs.structure(data["data"][0], Info)
使用轉換器有什么技巧嗎? 這需要為大約 70 個類完成,這就是為什么我認為 cattrs 可以現代化和簡化我正在嘗試做的事情。
謝謝
這是一種可能的解決方案。
這是策略:我們將通過包裝來自定義結構掛鈎。 默認鈎子期望輸入字典中的鍵與類的結構相匹配,但這里不是這種情況。 因此,我們將替換我們自己的結構掛鈎,它會進行一些預處理,然后調用默認掛鈎。
可以像這樣檢索 attrs 類cls
的默認掛鈎:
from cattrs import Converter
from cattrs.gen import make_dict_structure_fn
c = Converter()
handler = make_dict_structure_fn(cls, c)
知道了這一點,我們可以這樣實現一個輔助函數:
def group_by_prefix(cls: type, c: Converter, *prefixes: str) -> None:
handler = make_dict_structure_fn(cls, c)
def prefix_grouping_hook(val: dict[str, Any], _) -> Any:
by_prefix = {}
for key in val:
if "_" in key and (prefix := (parts := key.split("_", 1))[0]) in prefixes:
by_prefix.setdefault(prefix, {})[parts[1]] = val[key]
return handler(val | by_prefix, _)
c.register_structure_hook(cls, prefix_grouping_hook)
此函數采用 attrs 類cls
、轉換器和前綴列表。 然后它創建一個鈎子並將其注冊到類cls
的轉換器。 在內部,它會進行一些預處理以將數據打造成 cattrs 期望的形狀。
以下是如何將它用於Info
類:
>>> c = Converter()
>>> group_by_prefix(Info, c, "broadcaster", "subscriber", "moderator")
>>> print(c.structure(data["data"][0], Info))
Info(language='en', title='Weekend Events', delay=0, broadcaster=PartialUser(id=123, login='Sam'), subscriber=PartialUser(id=1234, login='Dave'), moderator=PartialUser(id=12345, login='Tom'))
您可以使用此方法根據需要使解決方案更加詳盡。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.