通过 Firestore 触发事件简化 python 中的字典

Rac*_*acu 6 python python-3.x google-cloud-platform google-cloud-firestore

我正在从更新 Cloud Firestore 触发器读取数据。这event是一个字典,包含键中的数据['value']['fields']。但是,每个键都包含一个嵌套字典,其中包含像'integerValue','booleanValue'或 之类的键'stringValue',其中 的值integerValue实际上是一个字符串。有没有一种方法可以删除“类型指针”?

我怎样才能转换这个:

{
    'fields': {
        'count': {
            'integerValue': '0'
        },
        'verified': {
            'booleanValue': False
        },
        'user': {
            'stringValue': 'Matt'
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

对此:

{
    'count': 0,
    'verified': False,
    'user': 'Matt',
}
Run Code Online (Sandbox Code Playgroud)

Pre*_*ham 8

最近我遇到了类似的问题。

我们可以递归地遍历地图来提取和简化事件触发数据。

这是 python 实现,从以前的答案扩展而来。

class FirestoreTriggerConverter(object):
    def __init__(self, client=None) -> None:
        self.client = client if client else firestore.client()
        self._action_dict = {
        'geoPointValue': (lambda x: dict(x)),
        'stringValue': (lambda x: str(x)),
        'arrayValue': (lambda x: [self._parse_value(value_dict) for value_dict in x.get("values", [])]),
        'booleanValue': (lambda x: bool(x)),
        'nullValue': (lambda x: None),
        'timestampValue': (lambda x: self._parse_timestamp(x)),
        'referenceValue': (lambda x: self._parse_doc_ref(x)),
        'mapValue': (lambda x: {key: self._parse_value(value) for key, value in x["fields"].items()}),
        'integerValue': (lambda x: int(x)),
        'doubleValue': (lambda x: float(x)),
    }

def convert(self, data_dict: dict) -> dict:
    result_dict = {}
    for key, value_dict in data_dict.items():
        result_dict[key] = self._parse_value(value_dict)
    return result_dict

def _parse_value(self, value_dict: dict) -> Any:
    data_type, value = value_dict.popitem()

    return self._action_dict[data_type](value)

def _parse_timestamp(self, timestamp: str):
    try:
        return datetime.strptime(timestamp, '%Y-%m-%dT%H:%M:%S.%fZ')
    except ValueError as e:
        return datetime.strptime(timestamp, '%Y-%m-%dT%H:%M:%SZ')

def _parse_doc_ref(self, doc_ref: str) -> DocumentReference:
    path_parts = doc_ref.split('/documents/')[1].split('/')
    collection_path = path_parts[0]
    document_path = '/'.join(path_parts[1:])

    doc_ref = self.client.collection(collection_path).document(document_path)
    return doc_ref
Run Code Online (Sandbox Code Playgroud)
按如下方式使用它
converter = FirestoreTriggerConverter(client)
simplified_data_dict = converter.convert(event_data_dict["event"]["value"]["fields"])
Run Code Online (Sandbox Code Playgroud)


Mad*_*ist 4

您可以创建已知类型的映射并以这种方式转换值:

types = {
    'integerValue': int,
    'booleanValue': bool,
    'stringValue': str,
}
Run Code Online (Sandbox Code Playgroud)

您可以通过以下方式替换像您拥有的嵌套字典一样的嵌套字典dict.popitem

replacement = {}
for key, meta in event['value']['fields'].items():
    typ, value = meta.popitem()
    replacement[key] = types[typ](value)
event['value'] = replacement
Run Code Online (Sandbox Code Playgroud)

您可以通过字典理解将其简化为一行:

event['value'] = {k: types[t](v) for k t, v in (k, *d.popitem()) for k, d in event['value']['fields'].items())}
Run Code Online (Sandbox Code Playgroud)