python - 如何以python中的功能方式将字符串转换为分层数据结构中的dict?
Posted
技术标签:
【中文标题】python - 如何以python中的功能方式将字符串转换为分层数据结构中的dict?【英文标题】:How to convert a string into dict in hierarchical data scructure the functional way in python? 【发布时间】:2021-11-30 22:43:31 【问题描述】:假设我有以下 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]
有更好的方法吗?
【问题讨论】:
【参考方案1】:对于这组特定的数据,您可以这样做:
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'])
【讨论】:
json.loads 可能比 eval 更安全,除非 OP 真的知道数据永远是安全的...... @2e0byo 请注意我在回答开头的评论 - 即,这可能不是解决此问题的通用方法【参考方案2】:退后一点,你为什么要这样做?以下是我能想到的几个原因,以及适当的解决方案:
因为我想自己实现 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")
如果你愿意,这个函数可以递归,返回最里面的元素。
我不知道这些原因是否正确涵盖了您的用例,但它们可能会有所帮助。基本方法(亲爱的函数式编程!)是将困难的逻辑放在一个函数中,然后如果你愿意,可以在你的理解中使用它。
JIT 解析解决方案
纯粹是为了好玩,因为这是在唠叨我,这里是一个类似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")
该类将解析dicts或dicts的json表示,并返回包装它们的JITParser对象,直到遇到无法解析为JSON的东西,在这种情况下,它将返回对象本身。
有很多可能的改进:你可以想到:
子类 dict 并拥有[]
访问权限
实现列表的递归解析
处理其他类型,例如带有.dotaccess
的对象。
等
但是模拟很有趣,它可能会激发你的灵感,所以我将把它留在这里。试试吧:这很有趣。
【讨论】:
以上是关于python - 如何以python中的功能方式将字符串转换为分层数据结构中的dict?的主要内容,如果未能解决你的问题,请参考以下文章
如何以编程方式列出 C++ 或 Python 中的 DLL 依赖项?
如何在 Python 中以不同方式处理列表中的最后一个元素?
如何以编程方式更改/更新 Python PyQt4 TableView 中的数据?