python - 为特定 id 值生成 json 输出时出错
问题描述
我有以下 json 树。
json_tree ={
"Garden": {
"Seaside": {
"@loc": "127.0.0.1",
"@myID": "1.3.1",
"Shoreside": {
"@myID": "3",
"InfoList": {
"Notes": {
"@code": "0",
"@myID": "1"
},
"Count": {
"@myID": "2",
"@val": "0"
}
},
"state": "0",
"Tid": "3",
"Lakesshore": {
"@myID": "4",
"InfoList": {
"Notes": {
"@code": "0",
"@oid": "1"
},
"Count": {
"@myID": "2",
"@val": "0"
}
},
"state": "0",
"Tid": "4"
}
},
"state": "0",
"Tid": "2"
},
"Tid": "1",
"state": "0"
}
}
我有一个方法,它接受“Tid”值并以以下格式返回输出。
这就是问题所在。我不明白为什么对于 的值Tid = 2
,我得到“错误”,说明InfoList
不存在。对于其他 Tid 值,它运行良好。有人可以帮我解决这个问题吗?
“ Tid InfoList
:”2 处没有,但我不确定如何更新我的逻辑来处理这个问题。
def get_output (d, id):
if isinstance(d, dict) and d.get('id') == id:
yield {"Tid": d['Tid'], "Notes": d['InfoList']['Notes']['@code'], "status": d['state']}
for i in getattr(d, "values", lambda: [])():
yield from get_based_on_id(i, id)
# The id is from 2 and higher
key_list = list(get_output (json_tree, id))
# To create the json result
jsonify(key_list if not key_list else key_list[0])
For "Tid" values of 2 and higher the get_output method creates this output:
{
"Tid": "3",
"Notes": "2000",
"state": "2"
}
下面显示的这部分效果很好。问题仅在于上面显示的代码。
def get_output_id_1 (d, id):
if isinstance(d, dict) and d.get('id') == id:
yield {"id": d['Tid'], "state": d['state']}
for i in getattr(d, "values", lambda: [])():
yield from get_root_id(i, id)
For "Tid" value of 1 and higher the get_output_id_1 method creates this output:
{
"Tid": "1",
"state": "1",
}
任何帮助表示赞赏。
解决方案
问题是您正在使用直接访问来利用可能在也可能不在字典中的键。要解决此问题,请使用该dict.get
方法,该方法将返回None
或您指定的一些默认值,以防密钥不存在:
small_example = {
'Tid': '2',
'status': 'some status'
}
# there is no InfoList key here, so to get around that, I can use something like:
info_list = small_example.get('InfoList')
repr(info_list)
None
get
现在,如果需要将事物链接在一起,您可以指定默认返回值,例如使用嵌套字典调用:
{
'Tid': small_example['Tid'],
'Notes': small_example.get('InfoList', {}).get('Notes', {}).get('@code'),
'status': small_example.get('state')
}
看看在前两个调用中,我如何返回一个空字典以防万一InfoList
和/或Notes
丢失,它支持后续调用get
. 没有它,我会得到一个AttributeError
:
small_example.get('InfoList').get('Notes')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'get'
所以你的yield
陈述应该是这样的:
yield {
"Tid": d['Tid'],
"Notes": d.get('InfoList', {}).get('Notes', {}).get('@code'),
"status": d.get('state')
}
编辑:如果你想要一个不同的默认值Notes
怎么办?
这有点棘手,特别是如果您想要一个不支持的数据结构.get
,例如str
.
您的yield
语句可能必须由不同的函数生成,以使事情更整洁:
# d is expected to be a dictionary
def create_yield(d):
# I'm using direct access on `Tid` because I'm assuming it should
# always be there, and if not it will raise a KeyError, you can
# modify this to fit your use case
container = {'Tid': d['Tid'],
'status': d.get('state')}
notes = small_example.get('InfoList', {}).get('Notes')
# if notes is a dict (not None), then we can get `@code` from it
if notes is not None:
container['Notes'] = notes.get('@code')
# otherwise, don't set the `Notes` attribute
return container
# later in your code at your yield statement
# you can call this function instead of manually building the dictionary
yield create_yield(small_example)
推荐阅读
- python - 如何检测图片上的斑马线?
- ios - 如何获得像“dictionary.count”返回值这样的全局定义?
- python - 熊猫获得所有非 Nan 值的列表
- reactjs - 蚂蚁设计中的拖放反应不起作用
- java - 按下电子邮件链接后,如何使 Android 重定向到特定活动?
- qt - QThread 如何从它自己的线程发送一个带有枚举作为 QML 消费参数的信号?
- vb.net - 我正在尝试将 Any+Time DatePicker/TimePicker 中的值传递给后面的 asp.net 代码
- react-native - 如何解决这个错误,Uncaught Error: 36.0.0 is not a valid SDK version。选项为 35.0.0、34.0.0、33.0.0、未版本
- ios - 使用 Flutter for iOS 检索订阅 IAP 产品列表
- python - 查找两个熊猫数据框之间的差异,并将所有内容添加到新的 DF