7

我有一些来自SOAPAPI的数据Suds,我需要在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"
      },
 }
4

6 回答 6

17

dict在类中有一个类方法suds.client.Client,它将 asudsobject作为输入并返回 Pythondict作为输出。在这里查看:官方 Suds 文档

生成的代码片段变得像这样优雅:

from suds.client import Client

# Code to obtain your suds_object here...

required_dict = Client.dict(suds_object)

您可能还想检查同一类中的items类方法(链接),该类方法从 suds_object 中提取项目,类似于items方法 on dict

于 2016-10-10T21:11:42.763 回答
8

您可以将对象强制转换为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)

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

于 2016-01-18T04:07:21.650 回答
4

通常情况下,正确答案在 docs 中。(括号)中的位是可以包含其他对象或类型的对象。

在这种情况下,我们有一个ArrayOfBalance包含类型列表的对象,每个类型都具有和Balance的属性。AmountCurrency

这些都可以使用.符号来引用,因此下面的单行代码可以解决问题。

balance = {item.Currency: item.Amount for item in response.Balance}  
于 2013-07-11T00:02:30.490 回答
4

找到了一个解决方案

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 只是嵌套的字典和列表,它应该可以工作。

于 2015-05-06T01:54:50.113 回答
3

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

在 IDLE 中,如果您键入>>>print response[0]后跟句点 '.' 符号你会得到一个弹出窗口,显示可以从这个级别访问的各种对象。

示例:如果您键入response[0]. 它将弹出一个弹出窗口并显示 Balance 对象,因此命令现在变为response[0].Balance.

您可以按照相同的方法获取后续级别下的对象列表

于 2014-12-25T21:12:58.167 回答
0

checkaayush 的答案不是递归的,因此它不考虑嵌套对象。

基于 aGuegu Answer 我做了一些更改以解决当 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
于 2018-02-22T13:15:23.500 回答