【问题标题】:Assign array to key dictionary in python [closed]在python中将数组分配给键字典[关闭]
【发布时间】:2016-10-09 00:13:20
【问题描述】:

我不是 python 专家。我不明白为什么我不能用这个 def 为这个字典的键分配一个值数组。

这就是我使用 sdk 定义的方式。

order_obj = Order(None)
order_obj.customerIp("14.140.42.67")
order_obj.merchantRefNum(RandomTokenGenerator().generateToken())
order_obj.currencyCode("CAD")
order_obj.totalAmount("1125")

redirect = Redirect(None)
redirect.rel("on_success")
redirect.uri("http://outwander.ca:{}/redirect")
return_keys_list = []
return_keys_list.append('id')
return_keys_list.append('transaction.amount')
redirect.returnKeys(return_keys_list)
redirect_list = []
redirect_list.append(redirect.__dict__)
order_obj.redirect(redirect_list)

这是我使用的sdk中的具体定义 https://github.com/OptimalPayments/Python_SDK/blob/63e1ae662a4447bd65c907563eec9effc602dd74/src/PythonNetBanxSDK/HostedPayment/Redirect.py

'''
Property Return Keys
'''   
def returnKeys(self, return_keys):
    self.__dict__['returnKeys'] = return_keys

从我可以调试的情况来看,将数组转换为要发送的 json 时出现问题。循环找到数组并尝试转换内部的元素(字符串),但默认情况下循环考虑每个给定的参数为数组,returnKeys参数被跳过...

'''
Serializing object
@param: Dictionary Object
@return: Serialized data
'''
def serialize(self, obj):
    return (json.dumps(self.to_dictionary(obj)))

'''
Convert object to a dictionary
@param: POJO Object
@return: Dictionary Object
'''
def to_dictionary(self, obj):
    obj_dict = dict()
    for key in obj.__dict__.keys():
        try:
            if(type(obj.__dict__[key]) is list):
                content = []
                for count in range(0, obj.__dict__[key].__len__()):
                    content.append(
                            self.to_dictionary(obj.__dict__[key][count]))
                obj_dict[key] = content
            elif(isinstance(obj.__dict__[key], DomainObject)):
                obj_dict[key] = self.to_dictionary(obj.__dict__[key])
            else:
                obj_dict[key] = obj.__dict__[key]
        except KeyError:
            pass
        except AttributeError:
            pass
    return (obj_dict)

我没有问题将一个键分配给一个值,但是当我尝试将一个数组分配给一个键时,它不起作用,它只是从 json 输出中忽略了这个键。

解决方案(黑客)

order_obj = Order(None)
order_obj.customerIp("14.140.42.67")
order_obj.merchantRefNum(RandomTokenGenerator().generateToken())
order_obj.currencyCode("CAD")
order_obj.totalAmount("1125")

redirect = Redirect(None)
redirect.rel("on_success")
redirect.uri("http://outwander.ca:{}/redirect")
redirect.returnKeys(('id', 'transaction.amount'))
redirect_list = []
redirect_list.append(redirect.__dict__)
order_obj.redirect((redirect_list))

【问题讨论】:

  • 所以问题出在您未包含在问题中的其他代码中?
  • 代码抛出异常 - 哪个代码,什么异常?您应该使用setattr() 而不是__dict__。见stackoverflow.com/questions/432786/…
  • @khelwood 包括我所知道的一切。我对 SDK 不熟悉,但它是开源的。
  • 请包含您遇到的异常
  • 我没有遇到任何异常。只是我没有得到预期的 json 字符串。相反,它是空的。我尝试在线使用python编译器为带有dict的键分配值并且它可以工作......所以我猜它在序列化中。您可能想查看 to_dictionary 定义...@rrauenza

标签: python arrays json dictionary sdk


【解决方案1】:

我已经复制了这个:

import json

class S:

    def serialize(self, obj):
        return (json.dumps(self.to_dictionary(obj)))

    def to_dictionary(self, obj):
        obj_dict = dict()
        for key in obj.__dict__.keys():
            try:
                if(type(obj.__dict__[key]) is list):
                    content = []
                    for count in range(0, obj.__dict__[key].__len__()):
                        content.append(self.to_dictionary(obj.__dict__[key][count]))
                    obj_dict[key] = content
                # elif(isinstance(obj.__dict__[key], DomainObject)):
                #    obj_dict[key] = self.to_dictionary(obj.__dict__[key])
                else:
                    obj_dict[key] = obj.__dict__[key]
            except KeyError:
                pass
            except AttributeError:
                pass
        return (obj_dict)


class A:
    def __init__(self):
        self.a = "1234"                                                         
        self.b = (1, 2, 3, 4)                                                   
        self.c = [1, 2, 3, 4]                                                   
        self.d = { 1: 2, 3: 4}               

print S().serialize(A())

输出:

{"a": "1234", "b": [1, 2, 3, 4], "d": {"1": 2, "3": 4}}

问题在于,当代码使用列表中的项目递归到to_dictionary() 时,代码总是期望它使用包含__dict__ 的对象进行递归。但是字符串(或 int)都不包含__dict__。 (我看到你在问题中也有类似的说法。)

我会在 github 上提交一个关于这个问题的问题。

除了修补他们的代码之外,您唯一的选择是创建一个包含您想要的项目的类。似乎它们不支持 stringint,除非作为 __dict__ 中的值。

您可以使用dict 作为列表:

class ReturnList:
    def __init__(self):
        self.list = { 1: "Item1", 2: "Item2" }

redirect.returnKeys(ReturnList())

附录:

等等!为什么元组案例有效?我认为你可以这样做:

redirect.returnKeys((1,2,3,4))

哦,我明白它为什么起作用了。这是一个错误。它们专门处理list,但不处理tuple,并且它不会递归tuple 类型。由于tuple 直接包含json-able 类型,它只是将其转换为json 列表。如果您的tuple 包含一个类或其他更复杂(非json)的对象,它将失败。

如果您想在本地修补他们的代码,或者要求他们修补他们的代码,可以像这样修改它以接受元组并正确处理 intstring

if(isinstance(obj.__dict__[key], (list, tuple)):
    for count in range(0, obj.__dict__[key].__len__()):
        item = obj.__dict__[key][count])
        if not isinstance(item, (str, int)):
            item = self.to_dictionary(obj.__dict__[key][count])
        content.append(item)

为了可维护性(如果您获得他们的 SDK 的新版本),我可能会想办法使用 dict 而不是 list 并将索引添加到您的 dict 中整数,类似于list。即foo = { 0: 'string1', 1: 'string2', 2: 'string3', }; redirect.returnKeys(foo)

list 转换为dict 的快速方法是使用

l = ['string1', 'string2', ]
dictified_list = dict(zip(l, range(0, len(l))))
redirect.returnkeys(dictified_list)

【讨论】:

  • 我不希望我的列表成为键。我想要一个 key.self.__dict__['returnKeys'] = return_keys 的多个值,其中 return_keys = 值数组
  • 已编辑...但我需要查看您使用的 SDK 以更好地了解您的问题。您可以在问题中包含您的错误消息吗?
  • 如何修复这个递归定义来处理字符串?
  • 把它们放在一个元组中。直到他们的 SDK 打破了这一点。或者将它们放在您用作列表的字典中。我的示例使用了数字,但字符串也可以正常工作。
  • 修复是指修复底层SDK代码吗?或者通过改变你传递的东西来解决?
猜你喜欢
  • 2018-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多