将sudsoap复杂数据类型解析为Python dict

将sudsoap复杂数据类型解析为Python dict,python,soap,dictionary,suds,Python,Soap,Dictionary,Suds,我有一些数据来自使用Suds的SOAPAPI,我需要在我的Python脚本中解析这些数据。在我开始编写解析器之前(不仅仅要做这个): 1) 有人知道这是什么吗?它是由Suds返回的标准复杂对象数据类型。我应该发现的 2) 如果是这样,是否有一个现有的库可以用来将其转换为Python字典?如何将该对象解析为Python dict?看来我可以把字典传给Suds,但找不到一个简单的方法把它拿出来 (ArrayOfBalance){ Balance[] = (Balance){

我有一些数据来自使用
Suds的
SOAP
API,我需要在我的
Python
脚本中解析这些数据。在我开始编写解析器之前(不仅仅要做这个):

1) 有人知道这是什么吗?它是由
Suds
返回的标准复杂对象数据类型。我应该发现的

2) 如果是这样,是否有一个现有的库可以用来将其转换为Python字典?如何将该对象解析为Python dict?看来我可以把字典传给Suds,但找不到一个简单的方法把它拿出来

(ArrayOfBalance){
   Balance[] = 
      (Balance){
         Amount = 0.0
         Currency = "EUR"
      },
      (Balance){
         Amount = 0.0
         Currency = "USD"
      },
      (Balance){
         Amount = 0.0
         Currency = "GBP"
      },
 }

正确的答案通常是。括号中的位是可以包含其他对象或类型的对象

在这种情况下,我们有一个
ArrayOfBalance
对象,它包含
余额
类型的列表,每个类型都有
金额
货币
属性

所有这些都可以使用
表示法来引用,因此下面的一行代码就起到了作用

balance = {item.Currency: item.Amount for item in response.Balance}  

我遇到了一个类似的问题,不得不阅读一篇关于肥皂水的回复。 Suds响应将作为由对象组成的元组返回。 len(response)将显示suds响应元组中包含的对象数。 为了访问第一个对象,我们需要给出
响应[0]

在空闲状态下,如果键入打印响应[0]
,后跟句点“.”符号,则会出现一个弹出窗口,显示可从此级别访问的各种对象

示例:如果键入
响应[0]
。它将弹出一个窗口并显示Balance对象,因此命令现在将变成
响应[0]。Balance

您可以按照相同的方法获取后续级别下的对象列表,找到一个:


如果sub只是嵌套的dict和list,那么它应该可以工作。

您可以将对象强制转换为
dict()
,但仍然可以获得sud使用的复杂数据类型。下面是我为这个场合写的一些有用的函数:

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)

如果有更简单的方法,我很想听听。

suds.client.client
类中有一个名为
dict
的类方法,它将
sudsobject
作为输入,并返回Python
dict
作为输出。在这里查看:

生成的代码片段变得非常优雅,如下所示:

from suds.client import Client

# Code to obtain your suds_object here...

required_dict = Client.dict(suds_object)

您可能还想签出从suds\u对象中提取项目的同一类中的
items
class方法(),类似于
dict
上的
items
方法

>P> > C.CKAYAUHU的答案不是递归的,所以它不考虑嵌套对象。 根据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

哇!我可以诚实地说,20年来,我从未见过这种形式的序列化。现在我必须知道这是什么lol。你能给我们一个数据的上下文吗?很高兴不仅仅是我!这是钱包余额的响应,它看起来像是某种自制的数据结构:-\正如我所怀疑的那样。但实际上它的行为就像一个对象。如果您尝试并响应.split(“,”),它会给出
AttributeError:ArrayOfBalance实例没有属性“split”
。我将进一步深入研究文档。现在我将其提交给python dic,如何从中提取信息。如果您嵌套了SudsObjects,那么它将毫无价值。这满足了我的一些要求-谢谢:)您提供的链接已失效-是否已在其他地方重新发布?请记住,这是5年前的事了,fedora主机似乎已经不存在了。我已经编辑了一份文档,但重要的部分在这里的答案中。

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