【问题标题】:Parsing Suds SOAP complex data type into Python dict将 Suds SOAP 复杂数据类型解析为 Python dict
【发布时间】:2013-07-09 00:53:56
【问题描述】:

我有一些来自使用SudsSOAP 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"
      },
 }

【问题讨论】:

  • 哇 .. 老实说,我在这方面做了 20 年,从未见过这种形式的连载。现在我必须知道那是什么哈哈。您能给我们提供数据的上下文吗?
  • 很高兴不仅仅是我!这是来自OKPay's API 的钱包余额回复
  • 好像是一些自制的数据结构:-\
  • 正如我所怀疑的那样。它实际上表现得像一个对象。如果您尝试使用 response.split(',') 它会给出AttributeError: ArrayOfBalance instance has no attribute 'split'。将深入研究文档。

标签: python soap dictionary suds


【解决方案1】:

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

生成的 sn-p 变得像这样优雅:

from suds.client import Client

# Code to obtain your suds_object here...

required_dict = Client.dict(suds_object)

您可能还想查看同一类中的 items 类方法 (link),它从 suds_object 中提取项目,类似于 dict 上的 items 方法。

【讨论】:

  • 现在我把它放到了一个 python dic 中,我如何从中提取信息。
  • 给你一个浅拷贝,如果你有嵌套的 sudsobjects 则毫无价值
  • 这满足了我的一些要求 - 谢谢 :)
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

    找到一个solution

    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,它应该可以工作。

    【讨论】:

      【解决方案4】:

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

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

      这些都可以使用. 表示法来引用,所以下面的单行代码就可以了。

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

      【讨论】:

      • 您提供的链接已失效 -- 是否已在其他地方重新托管?
      • 请记住,这是 5 年前的事了,fedora 主机似乎已经不存在了。我已在文档的获救副本中进行了编辑,但重要部分在此处的答案中。
      【解决方案5】:

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

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

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

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

      【讨论】:

        【解决方案6】:

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

        根据 aGuegu 回答,当 suds 对象在列表中包含字典时,我做了一些更改以解决问题。

        有效!

        
        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
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-09-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多