我有一組格式BBB如下的字串,我需要提取與text鍵對應的值(在下面的示例中是“我的生活很精彩”)。
BBB = str({"id": "18976", "episode_done": False, "text": "My life is amazing",
"text_candidates": ["My life is amazing", "I am worried about global warming"],
"metrics": {"clen": AverageMetric(12), "ctrunc": AverageMetric(0),
"ctrunclen": AverageMetric(0)}})
我嘗試轉換BBB為字串,然后使用json.loadand轉換為字典ast.literal_eval,但在這兩種情況下我都會收到錯誤訊息。我想這是因為metrics鍵有一個字典作為值。
你建議如何解決這個問題?謝謝。
uj5u.com熱心網友回復:
將字典作為值不是問題,這只是稱為嵌套字典,這非常好。
我不確定您的初始資料(及其型別)是什么,但這里有一個使用您的字典的演示。假設你有一本字典
BBB_dict = {
"id": "18976",
"episode_done": False,
"text": "My life is amazing",
"text_candidates": ["My life is amazing", "I am worried about global warming"],
"metrics": {
"clen": AverageMetric(12),
"ctrunc": AverageMetric(0),
"ctrunclen": AverageMetric(0)
}
}
您必須注意,呼叫str(BBB_dict)不會創建 JSON 字串。(相關)。要將這樣的字典轉換為 JSON 字串,您可以執行以下操作:
BBB = json.dumps(BBB_dict)
但這可能會為您引發以下例外:
TypeError: Object of type AverageMetric is not JSON serializable
AverageMetric嗯,那是因為 Python在從它創建 JSON 時不知道要使用你的類的哪些屬性。所以,你必須
def serialize(obj):
if isinstance(obj, AverageMetric):
return {
'x': obj.x,
'y': obj.y,
'z': obj.z
}
return {}
此方法指定在創建 JSON 時使用哪些欄位(即序列化 AverageMetrics 物件)。(相關)因此您可以按如下方式創建 JSON 字串:
BBB = json.dumps(BBB_dict, default=serialize)
這將導致以下結果:
'{"id": "18976", "episode_done": false, "text": "My life is amazing", "text_candidates": ["My life is amazing", "I am worried about global warming"], "metrics": {"clen": {"x": 12, "y": 1, "z": "z"}, "ctrunc": {"x": 0, "y": 1, "z": "z"}, "ctrunclen": {"x": 0, "y": 1, "z": "z"}}}'
uj5u.com熱心網友回復:
您可以將源代碼調整為ast.literal_eval()決議函式呼叫(和其他非文字)的內容,但轉換為字串:
import ast
BBB = """
{"id": "18976", "episode_done": False, "text": "My life is amazing",
"text_candidates": ["My life is amazing", "I am worried about global warming"],
"metrics": {"clen": AverageMetric(12), "ctrunc": AverageMetric(0),
"ctrunclen": AverageMetric(0)}}
""".strip()
def literal_eval_with_function_calls(source):
# Adapted from `ast.literal_eval`
def _convert(node):
if isinstance(node, list):
return [_convert(arg) for arg in node]
if isinstance(node, ast.Constant):
return node.value
if isinstance(node, ast.Tuple):
return tuple(map(_convert, node.elts))
if isinstance(node, ast.List):
return list(map(_convert, node.elts))
if isinstance(node, ast.Set):
return set(map(_convert, node.elts))
if isinstance(node, ast.Call) and isinstance(node.func, ast.Name) and node.func.id == 'set' and node.args == node.keywords == []:
return set()
if isinstance(node, ast.Dict):
return dict(zip(map(_convert, node.keys), map(_convert, node.values)))
if isinstance(node, ast.Expression):
return _convert(node.body)
return {
f'${node.__class__.__name__}': ast.get_source_segment(source, node),
}
return _convert(ast.parse(source, mode='eval'))
print(literal_eval_with_function_calls(BBB))
這輸出
{'episode_done': False,
'id': '18976',
'metrics': {'clen': {'$Call': 'AverageMetric(12)'},
'ctrunc': {'$Call': 'AverageMetric(0)'},
'ctrunclen': {'$Call': 'AverageMetric(0)'}},
'text': 'My life is amazing',
'text_candidates': ['My life is amazing', 'I am worried about global warming']}
但是,最好只使用不是不可決議格式的資料...
uj5u.com熱心網友回復:
您可以使用正則運算式:
import re
>>> re.findall('(?<="text": )"(.*)"', BBB)[0]
'My life is amazing'
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/423987.html
