我正在从Update Cloud Firestore触发器读取数据。 event
是一个字典,其中包含键['value']['fields']
中的数据。但是,每个键都包含一个嵌套的字典,其中包含'integerValue'
,'booleanValue'
或'stringValue'
之类的键,其中integerValue
的值实际上是一个字符串。有没有删除“类型指针”的方法?
我该如何转换:
{
'fields': {
'count': {
'integerValue': '0'
},
'verified': {
'booleanValue': False
},
'user': {
'stringValue': 'Matt'
}
}
}
对此:
{
'count': 0,
'verified': False,
'user': 'Matt',
}
答案 0 :(得分:1)
没有明确的方法可以这样做。您可以做的就是遍历现有词典,以获取新词典中所需的项目:
d = {
'fields': {
'count': {
'integerValue': '0'
},
'verified': {
'booleanValue': False
},
'user': {
'stringValue': 'Matt'
}
}
}
required = ['count', 'verified', 'user']
d1 = {}
for x in d.values():
for y in required:
if 'integerValue' in x[y].keys():
d1[y] = int(list(x[y].values())[0])
else:
d1[y] = list(x[y].values())[0]
print(d1)
# {'count': 0, 'verified': False, 'user': 'Matt'}
答案 1 :(得分:1)
在字典中使用keys()
origin_dict={
'fields': {
'count': {
'integerValue': '0'
},
'verified': {
'booleanValue': False
},
'user': {
'stringValue': 'Matt'
}
}
}
# remove first layer
b = origin_dict['fields']
new_dict = dict()
for i in b.keys():
# i will be second layer of dictionary
for j in b[i].keys():
# j will be third layer of dictionary
new_dict[i] = b[i][j]
print (new_dict)
答案 2 :(得分:1)
您可以创建已知类型的映射并以这种方式转换值:
types = {
'integerValue': int,
'booleanValue': bool,
'stringValue': str,
}
您可以通过dict.popitem
的魔力来替换嵌套词典,就像您拥有的那样:
replacement = {}
for key, meta in event['value']['fields'].items():
typ, value = meta.popitem()
replacement[key] = types[typ](value)
event['value'] = replacement
您可以通过字典理解将其简化为一个衬里:
event['value'] = {k: types[t](v) for k t, v in (k, *d.popitem()) for k, d in event['value']['fields'].items())}
答案 3 :(得分:1)
最近我遇到了类似的问题。
我们可以递归遍历地图以提取并简化事件触发数据。
这里是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["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
如下使用
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["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