簡體   English   中英

將 Suds SOAP 復雜數據類型解析為 Python dict

[英]Parsing Suds SOAP complex data type into Python dict

我有一些數據來自使用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"
      },
 }

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類型列表,每個類型都具有AmountCurrency屬性。

這些都可以使用. 符號,所以下面的單行代碼可以解決問題。

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM