[英]Parsing Suds SOAP complex data type into Python dict
我有一些数据来自使用Suds
的SOAP
API,我需要在我的Python
脚本中解析这些数据。 在我开始编写解析器之前(要做的不仅仅是这个):
1)
有人知道这是什么吗?
它是Suds
(documentation)返回的标准复杂对象数据类型。 应该发现了。
2)
如果是这样,是否有现有的库可用于将其转换为 Python 字典?
如何将此对象解析为 Python 字典? 似乎我可以将字典传递给 Suds,但看不到一种简单的方法将其取出。
(ArrayOfBalance){
Balance[] =
(Balance){
Amount = 0.0
Currency = "EUR"
},
(Balance){
Amount = 0.0
Currency = "USD"
},
(Balance){
Amount = 0.0
Currency = "GBP"
},
}
suds.client.Client
类中有一个名为dict
的类方法,它以sudsobject
作为输入并返回 Python dict
作为输出。 在这里查看: 官方 Suds 文档
结果片段变得如此优雅:
from suds.client import Client
# Code to obtain your suds_object here...
required_dict = Client.dict(suds_object)
您可能还想查看同一个类中的items
类方法( 链接),它从 suds_object 中提取类似于dict
上的items
方法的items
。
您可以将对象dict()
为dict()
,但您仍然会获得 suds 使用的复杂数据类型。 所以这里有一些我专门为这个场合写的有用的函数:
def basic_sobject_to_dict(obj):
"""Converts suds object to dict very quickly.
Does not serialize date time or normalize key case.
:param obj: suds object
:return: dict object
"""
if not hasattr(obj, '__keylist__'):
return obj
data = {}
fields = obj.__keylist__
for field in fields:
val = getattr(obj, field)
if isinstance(val, list):
data[field] = []
for item in val:
data[field].append(basic_sobject_to_dict(item))
else:
data[field] = basic_sobject_to_dict(val)
return data
def sobject_to_dict(obj, key_to_lower=False, json_serialize=False):
"""
Converts a suds object to a dict.
:param json_serialize: If set, changes date and time types to iso string.
:param key_to_lower: If set, changes index key name to lower case.
:param obj: suds object
:return: dict object
"""
import datetime
if not hasattr(obj, '__keylist__'):
if json_serialize and isinstance(obj, (datetime.datetime, datetime.time, datetime.date)):
return obj.isoformat()
else:
return obj
data = {}
fields = obj.__keylist__
for field in fields:
val = getattr(obj, field)
if key_to_lower:
field = field.lower()
if isinstance(val, list):
data[field] = []
for item in val:
data[field].append(sobject_to_dict(item, json_serialize=json_serialize))
elif isinstance(val, (datetime.datetime, datetime.time, datetime.date)):
data[field] = val.isoformat()
else:
data[field] = sobject_to_dict(val, json_serialize=json_serialize)
return data
def sobject_to_json(obj, key_to_lower=False):
"""
Converts a suds object to json.
:param obj: suds object
:param key_to_lower: If set, changes index key name to lower case.
:return: json object
"""
import json
data = sobject_to_dict(obj, key_to_lower=key_to_lower, json_serialize=True)
return json.dumps(data)
如果有更简单的方法,我很想听听。
找到了一个解决方案:
from suds.sudsobject import asdict
def recursive_asdict(d):
"""Convert Suds object into serializable format."""
out = {}
for k, v in asdict(d).iteritems():
if hasattr(v, '__keylist__'):
out[k] = recursive_asdict(v)
elif isinstance(v, list):
out[k] = []
for item in v:
if hasattr(item, '__keylist__'):
out[k].append(recursive_asdict(item))
else:
out[k].append(item)
else:
out[k] = v
return out
def suds_to_json(data):
return json.dumps(recursive_asdict(data))
如果 subs 只是嵌套的 dict 和 list,它应该可以工作。
通常情况下,正确答案 在 docs 中。 (括号)中的位是可以包含其他对象或类型的对象。
在本例中,我们有一个ArrayOfBalance
对象,其中包含一个Balance
类型列表,每个类型都具有Amount
和Currency
属性。
这些都可以使用.
符号,所以下面的单行代码可以解决问题。
balance = {item.Currency: item.Amount for item in response.Balance}
我遇到了类似的问题,不得不阅读 suds 回复。 Suds 响应将作为由对象组成的元组返回。 len(response) 将显示 suds 响应元组中包含的对象数量。 为了访问第一个对象,我们需要给出response[0]
。
在 IDLE 中,如果您键入>>>print response[0]
后跟一个句点“.” 符号,您将看到一个弹出窗口,显示可以从此级别访问的各种对象。
示例:如果您输入response[0]
。 它将带来一个弹出窗口并显示 Balance 对象,因此命令现在将变为response[0].Balance
。
您可以按照相同的方法获取后续级别下的对象列表
checkaayush 的答案不是递归的,所以它不考虑嵌套对象。
基于 aGuegu 答案,当 suds 对象在列表中有 dicts 时,我做了一些更改以解决问题。
它有效!
from suds.sudsobject import asdict
def recursive_asdict(d):
"""Convert Suds object into serializable format."""
out = {}
for k, v in asdict(d).items():
if hasattr(v, '__keylist__'):
out[k] = recursive_asdict(v)
elif isinstance(v, list):
out[k] = []
for item in v:
if hasattr(item, '__keylist__'):
out[k].append(recursive_asdict(item))
elif not isinstance(item, list):
out[k] = item
else:
out[k].append(item)
else:
out[k] = v
return out
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.