[英]How to convert a string into dict in hierarchical data scructure the functional way in python?
假設我有以下 python 數據結構,其中runtimeArgs
包含一個 json 字符串,而不是 python dict。
[
{
"runid":"57d45a60-2b34-11ec-8b92-16c898d5a004",
"properties":{
"runtimeArgs":"{\"date\":\"2021_10_11\",\"logical.start.time\":\"1634026435347\"}",
"phase-1":"7bc31901-2b34-11ec-9194-42010a0c0054"
}
},
{
"runid":"24f7887e-2b28-11ec-b60c-16c898d5a004",
"properties":{
"runtimeArgs":"{\"date\":\"2021_10_11\",\"logical.start.time\":\"1634021196053\"}",
"phase-1":"4712bfa1-2b28-11ec-8968-42010a0c005a"
}
}
]
# this is working
my_list[0]["properties"]['runtimeArgs']
# this not working
my_list[0]["properties"]['runtimeArgs']['date']
使用for
循環和json.loads()
我可以將其轉換為 python dict,但我想以更實用的方式執行此操作,例如: map或list comprehension等。
怎么可能做到這一點?
預期結果:
[
{
"runid":"57d45a60-2b34-11ec-8b92-16c898d5a004",
"properties":{
"runtimeArgs":{"date":"2021_10_11","logical.start.time":"1634026435347"},
"phase-1":"7bc31901-2b34-11ec-9194-42010a0c0054"
}
},
{
"runid":"24f7887e-2b28-11ec-b60c-16c898d5a004",
"properties":{
"runtimeArgs":{"date":"2021_10_11","logical.start.time":"1634021196053"},
"phase-1":"4712bfa1-2b28-11ec-8968-42010a0c005a"
}
}
]
# this should work
my_list[0]["properties"]['runtimeArgs']['date']
更新:
我可以自己解決的一種方法(我不喜歡)是這樣的:
[{**x, "properties": { "runtimeArgs" : json.loads(x["properties"]["runtimeArgs"]) }} for x in my_list if x]
有沒有更好的方法來做到這一點?
退后一點,你為什么要這樣做? 以下是我能想到的幾個原因,以及適當的解決方案:
因為我想自己實現 JSON 解析器,功能上,為了練習
在這種情況下,您主要靠自己,但一個可迭代的標記器可能是要走的路。
因為像從這個 json 格式的字符串中獲取元素 x 這樣簡單的事情應該很容易,而且我只需要做一次
在這種情況下,使用 json.loads,但將您的訪問權限封裝在一個函數中:
def get_json(json, key):
return json.loads(json)[key]
get_json(l[0]["properties"], "date") # this is a function. I reckon that's functional. Here with a comprehension:
{l["runid"]: get_json(x["properties"], "date") for x in l}
因為我想從結構中取出數據,邊走邊反序列化
使用一個函數:
def get_parse(thing, key):
try:
return thing[key]
except ValueError:
return json.loads(thing)[key]
get_parse(get_parse(l[0], "properties"), "date")
如果你願意,這個函數可以遞歸,返回最里面的元素。
我不知道這些原因是否正確涵蓋了您的用例,但它們可能會有所幫助。 基本方法(對函數式編程來說很重要!)是將困難的邏輯放在一個函數中,然后如果你願意的話,可以在你的理解中使用它。
純粹是為了好玩,因為這對我嘮叨,這里是一個類似 JS 的 JIT 解析類:
from json import loads
class JITParser:
def __init__(self, thing):
if not hasattr(thing, "__getitem__"):
self._thing = loads(thing)
else:
self._thing = thing
def get(self, key):
val = self._thing[key]
if isinstance(val, dict):
return JITParser(val)
else:
try:
return JITParser(loads(val))
except ValueError:
return val
def __repr__(self):
return f"JITParser with {repr(self._thing)}"
L = [
{
"runid": "57d45a60-2b34-11ec-8b92-16c898d5a004",
"properties": {
"runtimeArgs": '{"date":"2021_10_11","logical.start.time":"1634026435347"}',
"phase-1": "7bc31901-2b34-11ec-9194-42010a0c0054",
},
},
{
"runid": "24f7887e-2b28-11ec-b60c-16c898d5a004",
"properties": {
"runtimeArgs": '{"date":"2021_10_11","logical.start.time":"1634021196053"}',
"phase-1": "4712bfa1-2b28-11ec-8968-42010a0c005a",
},
},
]
j = JITParser(L[0])
j.get("runid")
j.get("properties")
j.get("properties").get("runtimeArgs")
j.get("properties").get("runtimeArgs").get("date")
此類將解析字典或字典的 json 表示,並返回包裝它們的 JITParser 對象,直到遇到無法解析為 JSON 的內容,在這種情況下,它將返回對象本身。
有很多可能的改進:你可以想到:
[]
訪問權限.dotaccess
對象。但模擬起來很有趣,它可能會激勵你,所以我會把它留在這里。 嘗試一下:這很有趣。
對於這組特定的數據,您可以這樣做:
L = [
{
"runid":"57d45a60-2b34-11ec-8b92-16c898d5a004",
"properties":{
"runtimeArgs":"{\"date\":\"2021_10_11\",\"logical.start.time\":\"1634026435347\"}",
"phase-1":"7bc31901-2b34-11ec-9194-42010a0c0054"
}
},
{
"runid":"24f7887e-2b28-11ec-b60c-16c898d5a004",
"properties":{
"runtimeArgs":"{\"date\":\"2021_10_11\",\"logical.start.time\":\"1634021196053\"}",
"phase-1":"4712bfa1-2b28-11ec-8968-42010a0c005a"
}
}
]
for d in L:
print(eval(d['properties']['runtimeArgs'])['date'])
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.